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
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 /* Global which holds the upper 16 bits of the last 32 bit area adress
50 * output. Useful only for iHex mode.
52 int lastExtendedAddress=-1;
54 /* Static variable which holds the index of last processed area.
55 * Useful only for iHex mode.
57 static int lastAreaIndex = -1;
59 /*)Function VOID reloc(c)
63 * The function reloc() calls a particular relocation
64 * function determined by the process code.
70 * int lkerr error flag
73 * int fprintf() c_library
74 * VOID rele() lkrloc.c
75 * VOID relp() lkrloc.c
76 * VOID relr() lkrloc.c
77 * VOId relt() lkrloc.c
80 * Refer to the called relocation functions.
107 fprintf(stderr, "Undefined Relocation Operation\n");
115 /*)Function VOID relt()
117 * The function relt() evaluates a T line read by
118 * the linker. Each byte value read is saved in the
119 * rtval[] array, rtflg[] is set, and the number of
120 * evaluations is maintained in rtcnt.
124 * T xx xx nn nn nn nn nn ...
127 * In: "T n0 n1 n2 n3 ... nn"
129 * Out: 0 1 2 .. rtcnt
130 * +----+----+----+----+----+
131 * rtval | n0 | n1 | n2 | .. | nn |
132 * +----+----+----+----+----+
133 * rtflag| 1 | 1 | 1 | 1 | 1 |
134 * +----+----+----+----+----+
136 * The T line contains the assembled code output by the assem-
137 * bler with xx xx being the offset address from the current area
138 * base address and nn being the assembled instructions and data in
145 * int rtcnt number of values evaluated
146 * int rtflg[] array of evaluation flags
147 * int rtval[] array of evaluation values
150 * int eval() lkeval.c
154 * Linker input T line evaluated.
164 rtval[rtcnt] = eval();
171 /*)Function VOID relr()
173 * The function relr() evaluates a R line read by
174 * the linker. The R line data is combined with the
175 * previous T line data to perform the relocation of
176 * code and data bytes. The S19 / IHX output and
177 * translation of the LST files to RST files may be
182 * R 0 0 nn nn n1 n2 xx xx ...
184 * The R line provides the relocation information to the linker.
185 * The nn nn value is the current area index, i.e. which area the
186 * current values were assembled. Relocation information is en-
187 * coded in groups of 4 bytes:
189 * 1. n1 is the relocation mode and object format
190 * 1. bit 0 word(0x00)/byte(0x01)
191 * 2. bit 1 relocatable area(0x00)/symbol(0x02)
192 * 3. bit 2 normal(0x00)/PC relative(0x04) relocation
193 * 4. bit 3 1-byte(0x00)/2-byte(0x08) object format for
195 * 5. bit 4 signed(0x00)/unsigned(0x10) byte data
196 * 6. bit 5 normal(0x00)/page '0'(0x20) reference
197 * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference
199 * 2. n2 is a byte index into the corresponding (i.e. pre-
200 * ceeding) T line data (i.e. a pointer to the data to be
201 * updated by the relocation). The T line data may be
202 * 1-byte or 2-byte byte data format or 2-byte word
205 * 3. xx xx is the area/symbol index for the area/symbol be-
206 * ing referenced. the corresponding area/symbol is found
207 * in the header area/symbol lists.
209 * The groups of 4 bytes are repeated for each item requiring relo-
210 * cation in the preceeding T line.
213 * areax **a pointer to array of area pointers
214 * int aindex area index
215 * char *errmsg[] array of pointers to error strings
216 * int error error code
217 * int lkerr error flag
218 * int mode relocation mode
219 * adrr_t paga paging base area address
220 * Addr_T pags paging symbol address
221 * Addr_T pc relocated base address
222 * Addr_T r PCR relocation value
223 * Addr_T reli relocation initial value
224 * Addr_T relv relocation final value
225 * int rindex symbol / area index
226 * Addr_T rtbase base code address
227 * Addr_T rtofst rtval[] index offset
228 * int rtp index into T data
229 * sym **s pointer to array of symbol pointers
232 * head *hp pointer to the head structure
233 * rerr rerr linker error structure
234 * FILE *stderr standard error device
237 * Addr_T adb_b() lkrloc.c
238 * Addr_T adb_lo() lkrloc.c
239 * Addr_T adb_hi() lkrloc.c
240 * Addr_T adw_w() lkrloc.c
241 * Addr_T evword() lkrloc.c
242 * int eval() lkeval.c
243 * int fprintf() c_library
245 * int lkulist lklist.c
247 * VOID relerr() lkrloc.c
249 * int symval() lksym.c
252 * The R and T lines are combined to produce
253 * relocated code and data. Output S19 / IHX
254 * and relocated listing files may be produced.
262 register Addr_T reli, relv;
263 int aindex, rindex, rtp, error;
264 Addr_T r, rtbase, rtofst, paga, pags, pc;
269 * Get area and symbol lists
277 if (eval() != (R_WORD | R_AREA) || eval()) {
278 fprintf(stderr, "R input error\n");
286 if (aindex >= hp->h_narea) {
287 fprintf(stderr, "R area error\n");
295 rtbase = adw_w(0, 0);
301 pc = adw_w(a[aindex]->a_addr, 0);
304 printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex,
305 a[aindex]->a_addr, a[aindex]->a_size, rtbase);
308 * Do remaining relocations
314 if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK)
316 mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval();
317 /* printf("unescaping rmode\n"); */
324 * R_SYM or R_AREA references
327 if (rindex >= hp->h_nglob) {
328 fprintf(stderr, "R symbol error\n");
332 reli = symval(s[rindex]);
334 if (rindex >= hp->h_narea) {
335 fprintf(stderr, "R area error\n");
339 reli = a[rindex]->a_addr;
347 reli -= (pc + (rtp-rtofst) + 1);
349 reli -= (pc + (rtp-rtofst) + 2);
354 * R_PAG0 or R_PAG addressing
356 if (mode & (R_PAG0 | R_PAG)) {
357 paga = sdp.s_area->a_addr;
363 * R_BYTE or R_WORD operation
368 /* This is a three byte address, of which
369 * we will select one byte.
373 /* printf("24 bit address selecting hi byte.\n"); */
374 relv = adb_24_hi(reli, rtp);
376 else if (mode & R_MSB)
378 /* Note that in 24 bit mode, R_MSB
379 * is really the middle byte, not
380 * the most significant byte.
382 * This is ugly and I can only apologize
385 /* printf("24 bit address selecting middle byte.\n"); */
386 relv = adb_24_mid(reli, rtp);
390 /* printf("24 bit address selecting lo byte.\n"); */
391 relv = adb_24_lo(reli, rtp);
394 else if (mode & R_BYT2) {
395 /* This is a two byte address, of
396 * which we will select one byte.
399 relv = adb_hi(reli, rtp);
401 relv = adb_lo(reli, rtp);
404 relv = adb_b(reli, rtp);
406 } else if (IS_R_J11(mode)) {
407 /* JLH: 11 bit jump destination for 8051. Forms
408 / two byte instruction with op-code bits
410 / rtp points at 3 byte locus: first two
411 / will get the instructiion. third one
415 /* Calculate absolute destination
416 / relv must be on same 2K page as pc
418 relv = adw_w(reli, rtp);
420 if ((relv & ~0x7ff) != ((pc + rtp - rtofst) & ~0x7ff)) {
424 /* Merge MSB (byte 0) with op-code, ignoring
425 / top 5 bits of address. Then hide the op-code
427 rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
431 else if (IS_R_J19(mode)) {
432 /* 19 bit jump destination for DS80C390. Forms
433 / three byte instruction with op-code bits
435 / rtp points at 4 byte locus: first three
436 / will get the instructiion. fourth one
440 /* Calculate absolute destination
441 / relv must be on same 512K page as pc
443 relv = adw_24(reli, rtp);
445 if ((relv & ~0x7ffff) != ((pc + rtp - rtofst) & ~0x7ffff)) {
449 /* Merge MSB (byte 0) with op-code, ignoring
450 / top 5 bits of address. Then hide the op-code
452 rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
456 else if (IS_C24(mode))
459 relv = adw_24(reli, rtp);
463 /* 16 bit address. */
464 relv = adw_w(reli, rtp);
468 * R_BYTE with R_BYT2 offset adjust
477 * Unsigned Byte Checking
479 if (mode & R_USGN && mode & R_BYTE && relv & ~0xFF)
483 * PCR Relocation Error Checking
485 if (mode & R_PCR && mode & R_BYTE) {
487 if (r != (Addr_T) ~0x7F && r != 0)
492 * Page Relocation Error Checking
494 /* if (mode & R_PAG0 && (relv & ~0xFF || paga || pags))
496 if (mode & R_PAG && (relv & ~0xFF))
503 rerr.aindex = aindex;
505 rerr.rtbase = rtbase + rtp - rtofst - 1;
506 rerr.rindex = rindex;
507 rerr.rval = relv - reli;
508 relerr(errmsg[error-1]);
516 /* JLH: output only if data (beyond two byte address) */
517 if ((oflag == 1) && (rtcnt > 2)) {
519 int extendedAddress = (a[aindex]->a_addr >> 16) & 0xffff;
521 /* Boy, is this a hack: for ABS sections, the
522 * base address is stored as zero, and the T records
523 * indicate the offset from zero.
525 * Since T records can only indicate a 16 bit offset, this
526 * obviously creates a problem for ABS segments located
527 * above 64K (this is only meaningful in flat24 mode).
529 * However, the size of an ABS area is stored as
530 * base address + section size (I suspect this is a bug,
531 * but it's a handy one right now). So the upper 8 bits of
532 * the 24 bit address are stored in the size record.
535 * This is another reason why we can't have areas greater
536 * than 64K yet, even in flat24 mode.
538 // extendedAddress += ((a[aindex]->a_size) >> 16 & 0xffff);
539 // commented out by jr
541 if (lastAreaIndex != aindex) {
542 lastAreaIndex = aindex;
546 if (extendedAddress != lastExtendedAddress)
549 if (lastExtendedAddress!=-1) {
550 printf("output extended linear address record 0x%x 0x%x\n",
551 extendedAddress, lastExtendedAddress);
556 ihxEntendedLinearAddress(extendedAddress);
558 else if (extendedAddress)
560 /* Not allowed to generate extended address records,
561 * but one is called for here...
564 "warning: extended linear address encountered; "
565 "you probably want the -r flag.\n");
567 lastExtendedAddress = extendedAddress;
572 if ((oflag == 2) && (rtcnt > 2)) {
578 "Unsigned Byte error",
579 "Byte PCR relocation error",
580 "Page0 relocation error",
581 "Page Mode relocation error"
585 /*)Function VOID relp()
587 * The function relp() evaluates a P line read by
588 * the linker. The P line data is combined with the
589 * previous T line data to set the base page address
590 * and test the paging boundary and length.
594 * P 0 0 nn nn n1 n2 xx xx
596 * The P line provides the paging information to the linker as
597 * specified by a .setdp directive. The format of the relocation
598 * information is identical to that of the R line. The correspond-
599 * ing T line has the following information:
600 * T xx xx aa aa bb bb
602 * Where aa aa is the area reference number which specifies the
603 * selected page area and bb bb is the base address of the page.
604 * bb bb will require relocation processing if the 'n1 n2 xx xx' is
605 * specified in the P line. The linker will verify that the base
606 * address is on a 256 byte boundary and that the page length of an
607 * area defined with the PAG type is not larger than 256 bytes.
610 * areax **a pointer to array of area pointers
611 * int aindex area index
612 * int mode relocation mode
613 * Addr_T relv relocation value
614 * int rindex symbol / area index
615 * int rtp index into T data
616 * sym **s pointer to array of symbol pointers
619 * head *hp pointer to the head structure
620 * int lkerr error flag
621 * sdp sdp base page structure
622 * FILE *stderr standard error device
625 * Addr_T adw_w() lkrloc.c
626 * Addr_T evword() lkrloc.c
627 * int eval() lkeval.c
628 * int fprintf() c_library
630 * int symval() lksym.c
633 * The P and T lines are combined to set
634 * the base page address and report any
642 register int aindex, rindex;
649 * Get area and symbol lists
657 if (eval() != (R_WORD | R_AREA) || eval()) {
658 fprintf(stderr, "P input error\n");
666 if (aindex >= hp->h_narea) {
667 fprintf(stderr, "P area error\n");
673 * Do remaining relocations
681 * R_SYM or R_AREA references
684 if (rindex >= hp->h_nglob) {
685 fprintf(stderr, "P symbol error\n");
689 relv = symval(s[rindex]);
691 if (rindex >= hp->h_narea) {
692 fprintf(stderr, "P area error\n");
696 relv = a[rindex]->a_addr;
705 if (aindex >= hp->h_narea) {
706 fprintf(stderr, "P area error\n");
710 sdp.s_areax = a[aindex];
711 sdp.s_area = sdp.s_areax->a_bap;
712 sdp.s_addr = adw_w(0,4);
713 if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
714 relerp("Page Definition Boundary Error");
717 /*)Function VOID rele()
719 * The function rele() closes all open output files
720 * at the end of the linking process.
726 * int oflag output type flag
727 * int uflag relocation listing flag
731 * VOID lkulist() lklist.c
735 * All open output files are closed.
753 /*)Function Addr_T evword()
755 * The function evword() combines two byte values
756 * into a single word value.
759 * Addr_T v temporary evaluation variable
762 * hilo byte ordering parameter
765 * int eval() lkeval.c
768 * Relocation text line is scanned to combine
769 * two byte values into a single word value.
788 /*)Function Addr_T adb_b(v, i)
790 * int v value to add to byte
791 * int i rtval[] index
793 * The function adb_b() adds the value of v to
794 * the single byte value contained in rtval[i].
795 * The new value of rtval[i] is returned.
807 * The value of rtval[] is changed.
816 return(rtval[i] += v);
819 /*)Function Addr_T adb_lo(v, i)
821 * int v value to add to byte
822 * int i rtval[] index
824 * The function adb_lo() adds the value of v to the
825 * double byte value contained in rtval[i] and rtval[i+1].
826 * The new value of rtval[i] / rtval[i+1] is returned.
827 * The MSB rtflg[] is cleared.
830 * Addr_T j temporary evaluation variable
833 * hilo byte ordering parameter
839 * The value of rtval[] is changed.
840 * The rtflg[] value corresponding to the
841 * MSB of the word value is cleared to reflect
842 * the fact that the LSB is the selected byte.
865 /*)Function Addr_T adb_hi(v, i)
867 * int v value to add to byte
868 * int i rtval[] index
870 * The function adb_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 LSB rtflg[] is cleared.
876 * Addr_T j temporary evaluation variable
879 * hilo byte ordering parameter
885 * The value of rtval[] is changed.
886 * The rtflg[] value corresponding to the
887 * LSB of the word value is cleared to reflect
888 * the fact that the MSB is the selected byte.
911 /*)Function Addr_T adb_24_hi(v, i)
913 * int v value to add to byte
914 * int i rtval[] index
916 * The function adb_24_hi() adds the value of v to the
917 * 24 bit value contained in rtval[i] - rtval[i+2].
918 * The new value of rtval[i] / rtval[i+1] is returned.
919 * The LSB & middle byte rtflg[] is cleared.
922 * Addr_T j temporary evaluation variable
925 * hilo byte ordering parameter
931 * The value of rtval[] is changed.
932 * The rtflg[] value corresponding to the
933 * LSB & middle byte of the word value is cleared to
934 * reflect the fact that the MSB is the selected byte.
939 adb_24_hi(Addr_T v, int i)
945 /* Remove the lower two bytes. */
959 /*)Function Addr_T adb_24_mid(v, i)
961 * int v value to add to byte
962 * int i rtval[] index
964 * The function adb_24_mid() adds the value of v to the
965 * 24 bit value contained in rtval[i] - rtval[i+2].
966 * The new value of rtval[i] / rtval[i+1] is returned.
967 * The LSB & MSB byte rtflg[] is cleared.
970 * Addr_T j temporary evaluation variable
973 * hilo byte ordering parameter
979 * The value of rtval[] is changed.
980 * The rtflg[] value corresponding to the
981 * LSB & MSB of the 24 bit value is cleared to reflect
982 * the fact that the middle byte is the selected byte.
987 adb_24_mid(Addr_T v, int i)
993 /* remove the MSB & LSB. */
1000 /*)Function Addr_T adb_24_lo(v, i)
1002 * int v value to add to byte
1003 * int i rtval[] index
1005 * The function adb_24_lo() adds the value of v to the
1006 * 24 bit value contained in rtval[i] - rtval[i+2].
1007 * The new value of rtval[i] / rtval[i+1] is returned.
1008 * The MSB & middle byte rtflg[] is cleared.
1011 * Addr_T j temporary evaluation variable
1014 * hilo byte ordering parameter
1020 * The value of rtval[] is changed.
1021 * The rtflg[] value corresponding to the
1022 * MSB & middle byte of the word value is cleared to
1023 * reflect the fact that the LSB is the selected byte.
1028 adb_24_lo(Addr_T v, int i)
1034 /* Remove the upper two bytes. */
1048 /*)Function Addr_T adw_w(v, i)
1050 * int v value to add to word
1051 * int i rtval[] index
1053 * The function adw_w() adds the value of v to the
1054 * word value contained in rtval[i] and rtval[i+1].
1055 * The new value of rtval[i] / rtval[i+1] is returned.
1058 * Addr_T j temporary evaluation variable
1061 * hilo byte ordering parameter
1067 * The word value of rtval[] is changed.
1079 j = v + (rtval[i] << 8) + (rtval[i+1] & 0xff);
1080 rtval[i] = (j >> 8) & 0xff;
1081 rtval[i+1] = j & 0xff;
1083 j = v + (rtval[i] & 0xff) + (rtval[i+1] << 8);
1084 rtval[i] = j & 0xff;
1085 rtval[i+1] = (j >> 8) & 0xff;
1090 /*)Function Addr_T adw_24(v, i)
1092 * int v value to add to word
1093 * int i rtval[] index
1095 * The function adw_w() adds the value of v to the
1096 * 24 bit value contained in rtval[i] - rtval[i+2].
1097 * The new value of rtval[i] - rtval[i+2] is returned.
1100 * Addr_T j temporary evaluation variable
1103 * hilo byte ordering parameter
1109 * The word value of rtval[] is changed.
1113 adw_24(Addr_T v, int i)
1118 j = v + ((rtval[i] & 0xff) << 16)
1119 + ((rtval[i+1] & 0xff) << 8)
1120 + (rtval[i+2] & 0xff);
1121 rtval[i] = (j >> 16) & 0xff;
1122 rtval[i+1] = (j >> 8) & 0xff;
1123 rtval[i+2] = j & 0xff;
1125 j = v + (rtval[i] & 0xff)
1126 + ((rtval[i+1] & 0xff) << 8)
1127 + ((rtval[i+2] & 0xff) << 16);
1128 rtval[i] = j & 0xff;
1129 rtval[i+1] = (j >> 8) & 0xff;
1130 rtval[i+2] = (j >> 16) & 0xff;
1135 /*)Function Addr_T adw_lo(v, i)
1137 * int v value to add to byte
1138 * int i rtval[] index
1140 * The function adw_lo() adds the value of v to the
1141 * double byte value contained in rtval[i] and rtval[i+1].
1142 * The new value of rtval[i] / rtval[i+1] is returned.
1143 * The MSB rtval[] is zeroed.
1146 * Addr_T j temporary evaluation variable
1149 * hilo byte ordering parameter
1155 * The value of rtval[] is changed.
1156 * The MSB of the word value is cleared to reflect
1157 * the fact that the LSB is the selected byte.
1180 /*)Function Addr_T adw_hi(v, i)
1182 * int v value to add to byte
1183 * int i rtval[] index
1185 * The function adw_hi() adds the value of v to the
1186 * double byte value contained in rtval[i] and rtval[i+1].
1187 * The new value of rtval[i] / rtval[i+1] is returned.
1188 * The MSB and LSB values are interchanged.
1189 * The MSB rtval[] is zeroed.
1192 * Addr_T j temporary evaluation variable
1195 * hilo byte ordering parameter
1201 * The value of rtval[] is changed.
1202 * The MSB and LSB values are interchanged and
1203 * then the MSB cleared.
1216 * LSB = MSB, Clear MSB
1219 rtval[i+1] = rtval[i];
1222 rtval[i] = rtval[i+1];
1228 /*)Function VOID relerr(str)
1230 * char *str error string
1232 * The function relerr() outputs the error string to
1233 * stderr and to the map file (if it is open).
1239 * FILE *mfp handle for the map file
1242 * VOID errdmp() lkrloc.c
1245 * Error message inserted into map file.
1253 errdmp(stderr, str);
1258 /*)Function VOID errdmp(fptr, str)
1260 * FILE *fptr output file handle
1261 * char *str error string
1263 * The function errdmp() outputs the error string str
1264 * to the device specified by fptr. Additional information
1265 * is output about the definition and referencing of
1266 * the symbol / area error.
1269 * int mode error mode
1270 * int aindex area index
1271 * int lkerr error flag
1272 * int rindex error index
1273 * sym **s pointer to array of symbol pointers
1274 * areax **a pointer to array of area pointers
1275 * areax *raxp error area extension pointer
1278 * sdp sdp base page structure
1281 * int fprintf() c_library
1282 * VOID prntval() lkrloc.c
1294 int mode, aindex, rindex;
1303 aindex = rerr.aindex;
1304 rindex = rerr.rindex;
1309 fprintf(fptr, "\n?ASlink-Warning-%s", str);
1313 * Print symbol if symbol based
1316 fprintf(fptr, " for symbol %s\n",
1317 &s[rindex]->s_id[0]);
1319 fprintf(fptr, "\n");
1326 " file module area offset\n");
1328 " Refby %-8.8s %-8.8s %-8.8s ",
1331 &a[aindex]->a_bap->a_id[0]);
1332 prntval(fptr, rerr.rtbase);
1338 raxp = s[rindex]->s_axp;
1343 " Defin %-8.8s %-8.8s %-8.8s ",
1344 raxp->a_bhp->h_lfile->f_idp,
1345 &raxp->a_bhp->m_id[0],
1346 &raxp->a_bap->a_id[0]);
1348 prntval(fptr, s[rindex]->s_addr);
1350 prntval(fptr, rerr.rval);
1354 /*)Function VOID prntval(fptr, v)
1356 * FILE *fptr output file handle
1357 * Addr_T v value to output
1359 * The function prntval() outputs the value v, in the
1360 * currently selected radix, to the device specified
1367 * int xflag current radix
1370 * int fprintf() c_library
1383 fprintf(fptr, "%04X\n", v);
1386 fprintf(fptr, "%06o\n", v);
1389 fprintf(fptr, "%05u\n", v);
1393 /*)Function VOID relerp(str)
1395 * char *str error string
1397 * The function relerp() outputs the paging error string to
1398 * stderr and to the map file (if it is open).
1404 * FILE *mfp handle for the map file
1407 * VOID erpdmp() lkrloc.c
1410 * Error message inserted into map file.
1418 erpdmp(stderr, str);
1423 /*)Function VOID erpdmp(fptr, str)
1425 * FILE *fptr output file handle
1426 * char *str error string
1428 * The function erpdmp() outputs the error string str
1429 * to the device specified by fptr.
1432 * head *thp pointer to head structure
1435 * int lkerr error flag
1436 * sdp sdp base page structure
1439 * int fprintf() c_library
1440 * VOID prntval() lkrloc.c
1452 register struct head *thp;
1454 thp = sdp.s_areax->a_bhp;
1459 fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1466 " file module pgarea pgoffset\n");
1468 " PgDef %-8.8s %-8.8s %-8.8s ",
1469 thp->h_lfile->f_idp,
1471 &sdp.s_area->a_id[0]);
1472 prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);