1 /* lkrloc3.c */
2 
3 /*
4  *  Copyright (C) 1989-2010  Alan R. Baldwin
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
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.
15  *
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/>.
18  *
19  *
20  * Alan R. Baldwin
21  * 721 Berkeley St.
22  * Kent, Ohio  44240
23  *
24  *   With enhancements from:
25  *
26  *      John L. Hartman (JLH)
27  *      jhartman@compuserve.com
28  *
29  *      Bill McKinnon (BM)
30  *      w_mckinnon@conknet.com
31  */
32 
33 #include "aslink.h"
34 
35 /*)Module       lkrloc3.c
36  *
37  *      The module lkrloc3.c contains the functions which
38  *      perform the version 3 relocation calculations.
39  *
40  *      lkrloc3.c contains the following functions:
41  *              a_uint  adb_lo()
42  *              a_uint  adb_hi()
43  *              VOID    erpdmp3()
44  *              VOID    errdmp3()
45  *              VOID    rele3()
46  *              VOID    relerr3()
47  *              VOID    relerp3()
48  *              VOID    reloc3()
49  *              VOID    relp3()
50  *              VOID    relr3()
51  *              VOID    relt3()
52  *
53  *      lkrloc3.c the local variable errmsg3[].
54  *
55  */
56 
57 /*)Function VOID        reloc3(c)
58  *
59  *                      int c           process code
60  *
61  *      The function reloc3() calls a particular relocation
62  *      function determined by the process code.
63  *
64  *      local variable:
65  *              none
66  *
67  *      global variables:
68  *              int lkerr                       error flag
69  *
70  *      called functions:
71  *              int fprintf()           c_library
72  *              VOID    rele3()         lkrloc3.c
73  *              VOID    relp3()         lkrloc3.c
74  *              VOID    relr3()         lkrloc3.c
75  *              VOId    relt3()         lkrloc3.c
76  *
77  *      side effects:
78  *              Refer to the called relocation functions.
79  *
80  */
81 
82 VOID
reloc3(int c)83 reloc3(int c)
84 {
85         switch(c) {
86 
87         case 'T':
88                 relt3();
89                 break;
90 
91         case 'R':
92                 relr3();
93                 break;
94 
95         case 'P':
96                 relp3();
97                 break;
98 
99         case 'E':
100                 rele3();
101                 break;
102 
103         default:
104                 fprintf(stderr, "Undefined Relocation Operation\n");
105                 lkerr++;
106                 break;
107 
108         }
109 }
110 
111 
112 /*)Function VOID        relt3()
113  *
114  *      The function relt3() evaluates a T line read by
115  *      the linker. Each byte value read is saved in the
116  *      rtval[] array, rtflg[] is set, and the number of
117  *      evaluations is maintained in rtcnt.
118  *
119  *              T Line
120  *
121  *              T xx xx nn nn nn nn nn ...
122  *
123  *
124  *              In: "T n0 n1 n2 n3 ... nn"
125  *
126  *              Out:     0       1        2    ..  rtcnt
127  *                        +----+----+----+----+----+
128  *              rtval | n0 | n1 | n2 | .. | nn |
129  *                        +----+----+----+----+----+
130  *              rtflag|  1 |  1 |  1 |  1 |  1 |
131  *                        +----+----+----+----+----+
132  *
133  *      The T line contains the assembled code output by the assem-
134  *      bler with xx xx being the offset address from the current area
135  *      base address and nn being the assembled instructions and data in
136  *      byte format.
137  *
138  *      local variable:
139  *              none
140  *
141  *      global variables:
142  *              int rtcnt               number of values evaluated
143  *              int rtflg[]             array of evaluation flags
144  *              int rtval[]             array of evaluation values
145  *
146  *      called functions:
147  *              int eval()              lkeval.c
148  *              int more()              lklex.c
149  *
150  *      side effects:
151  *              Linker input T line evaluated.
152  *
153  */
154 
155 VOID
relt3(void)156 relt3(void)
157 {
158         rtcnt = 0;
159         while (more()) {
160                 if (rtcnt < NTXT) {
161                         rtval[rtcnt] = eval();
162                         rtflg[rtcnt] = 1;
163                         rterr[rtcnt] = 0;
164                         rtcnt++;
165                 }
166         }
167 }
168 
169 /*)Function     VOID    relr3()
170  *
171  *      The function relr3() evaluates a R line read by
172  *      the linker.  The R line data is combined with the
173  *      previous T line data to perform the relocation of
174  *      code and data bytes.  The S19 / IHX output and
175  *      translation of the LST files to RST files may be
176  *      performed.
177  *
178  *              R Line
179  *
180  *              R 0 0 nn nn n1 n2 xx xx ...
181  *
182  *      The R line provides the relocation information to the linker.
183  *      The nn nn value is the current area index, i.e.  which area  the
184  *      current  values  were  assembled.  Relocation information is en-
185  *      coded in groups of 4 bytes:
186  *
187  *      1.  n1 is the relocation mode and object format
188  *              1.  bit 0 word(0x00)/byte(0x01)
189  *              2.  bit 1 relocatable area(0x00)/symbol(0x02)
190  *              3.  bit 2 normal(0x00)/PC relative(0x04) relocation
191  *              4.  bit 3 1-byte(0x00)/2-byte(0x08) byte data
192  *              5.  bit 4 signed(0x00)/unsigned(0x10) byte data
193  *              6.  bit 5 normal(0x00)/page '0'(0x20) reference
194  *              7.  bit 6 normal(0x00)/page 'nnn'(0x40) reference
195  *
196  *      2.  n2  is  a byte index into the corresponding (i.e.  pre-
197  *              ceeding) T line data (i.e.  a pointer to the data to be
198  *              updated  by  the  relocation).   The T line data may be
199  *              1-byte or  2-byte  byte  data  format  or  2-byte  word
200  *              format.
201  *
202  *      3.  xx xx  is the area/symbol index for the area/symbol be-
203  *              ing referenced.  the corresponding area/symbol is found
204  *              in the header area/symbol lists.
205  *
206  *      The groups of 4 bytes are repeated for each item requiring relo-
207  *      cation in the preceeding T line.
208  *
209  *      local variable:
210  *              areax   **a             pointer to array of area pointers
211  *              int     aindex          area index
212  *              char    *errmsg3[]      array of pointers to error strings
213  *              int     error           error code
214  *              int     mode            relocation mode
215  *              adrr_t  paga            paging base area address
216  *              a_uint  pags            paging symbol address
217  *              a_uint  r               PCR relocation value
218  *              a_uint  reli            relocation initial value
219  *              a_uint  relv            relocation final value
220  *              int     rindex          symbol / area index
221  *              a_uint  rtbase          base code address
222  *              a_uint  rtofst          rtval[] index offset
223  *              int rtp                 index into T data
224  *              sym **s                 pointer to array of symbol pointers
225  *
226  *      global variables:
227  *              head    *hp             pointer to the head structure
228  *              int     lkerr           error flag
229  *              a_uint  pc              relocated base address
230  *              int     pcb             bytes per instruction word
231  *              rerr    rerr            linker error structure
232  *              FILE    *stderr         standard error device
233  *
234  *      called functions:
235  *              a_uint  adb_1b()        lkrloc.c
236  *              a_uint  adb_2b()        lkrloc.c
237  *              a_uint  adb_lo()        lkrloc3.c
238  *              a_uint  adb_hi()        lkrloc3.c
239  * sdld specific
240  *              VOID    elf()           lkelf.c
241  *              VOID    gb()            lkgb.c
242  * end sdld specific
243  *              a_uint  evword()        lkrloc.c
244  *              int     eval()          lkeval.c
245  *              int     fprintf()       c_library
246  *              VOID    ihx()           lkihx.c
247  *              VOID    s19()           lks19.c
248  *              VOID    lkulist         lklist.c
249  *              int     more()          lklex.c
250  *              VOID    relerr3()       lkrloc3.c
251  *              int     symval()        lksym.c
252  *
253  *      side effects:
254  *              The R and T lines are combined to produce
255  *              relocated code and data.  Output Sxx / Ixx
256  *              and relocated listing files may be produced.
257  *
258  */
259 
260 VOID
relr3(void)261 relr3(void)
262 {
263         int mode;
264         a_uint reli, relv;
265         int aindex, rindex, rtp, error, i;
266         a_uint r, rtbase, rtofst, paga = 0, pags = 0;
267         struct areax **a;
268         struct sym **s;
269 
270         /*
271          * Get area and symbol lists
272          */
273         a = hp->a_list;
274         s = hp->s_list;
275 
276         /*
277          * Verify Area Mode
278          */
279         if (eval() != (R3_WORD | R3_AREA) || eval()) {
280                 fprintf(stderr, "R input error\n");
281                 lkerr++;
282                 return;
283         }
284 
285         /*
286          * Get area pointer
287          */
288         aindex = (int) evword();
289         if (aindex >= hp->h_narea) {
290                 fprintf(stderr, "R area error\n");
291                 lkerr++;
292                 return;
293         }
294 
295         /*
296          * Select Output File
297          */
298         if (oflag != 0) {
299                 ap = a[aindex]->a_bap;
300                 if (ofp != NULL) {
301                         rtabnk->b_rtaflg = rtaflg;
302                         if (ofp != ap->a_ofp) {
303                                 lkflush();
304                         }
305                 }
306                 ofp = ap->a_ofp;
307                 rtabnk = ap->a_bp;
308                 rtaflg = rtabnk->b_rtaflg;
309         }
310 
311         /*
312          * Base values
313          */
314         rtbase = adb_xb(0, 0);
315         rtofst = a_bytes;
316 
317         /*
318          * Relocate address
319          */
320         pc = adb_xb(a[aindex]->a_addr, 0);
321 
322         /*
323          * Number of 'bytes' per PC address
324          */
325         pcb = 1;
326 
327         #if 0
328         printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex,
329                 a[aindex]->a_addr, a[aindex]->a_size, rtbase);
330         #endif
331         /*
332          * Do remaining relocations
333          */
334         while (more()) {
335                 error = 0;
336                 mode = (int) eval();
337 
338                 if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK)
339                 {
340                         mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval();
341                         /* printf("unescaping rmode\n"); */
342                 }
343 
344                 rtp = (int) eval();
345                 rindex = (int) evword();
346 
347                 /*
348                  * R3_SYM or R3_AREA references
349                  */
350                 if (mode & R3_SYM) {
351                         if (rindex >= hp->h_nsym) {
352                                 fprintf(stderr, "R symbol error\n");
353                                 lkerr++;
354                                 return;
355                         }
356                         reli = symval(s[rindex]);
357                 }
358 /* sdld specific */
359                 else if ((IS_R_J11(mode) || IS_R_J19(mode)) && (rindex == 0xFFFF)) {
360                         /* absolute acall/ajmp address */
361                         reli = 0;
362                 }
363 /* end sdld specific */
364                 else {
365                         if (rindex >= hp->h_narea) {
366                                 fprintf(stderr, "R area error\n");
367                                 lkerr++;
368                                 return;
369                         }
370                         reli = a[rindex]->a_addr;
371                 }
372 
373                 /*
374                  * R3_PCR addressing
375                  */
376                 if (mode & R3_PCR) {
377                         if (mode & R3_BYTE) {
378                                 reli -= (pc + (rtp-rtofst) + 1);
379                         } else {
380                                 reli -= (pc + (rtp-rtofst) + 2);
381                         }
382                 }
383 
384                 /*
385                  * R3_PAG0 or R3_PAG addressing
386                  */
387                 if (mode & (R3_PAG0 | R3_PAG)) {
388                         paga  = sdp.s_area->a_addr;
389                         pags  = sdp.s_addr;
390                         reli -= paga + pags;
391                 }
392 
393 
394                 /* pdk instruction fusion */
395                 if (TARGET_IS_PDK) {
396                         relv = adb_3b(reli, rtp);
397 
398                         /* pdk addresses in words, not in bytes,
399                          * for goto/call instructions and byte selections.
400                          */
401                         int jump = 1, mask = 0;
402                         if (rtval[rtp + 4] == 15) {
403                                 jump = rtval[rtp + 3] & 0x70;
404                                 mask = 0x40;
405                                 if (get_sdld_target() == TARGET_ID_PDK) {
406                                         set_sdld_target(TARGET_ID_PDK15);
407                                 } else if (get_sdld_target() != TARGET_ID_PDK15) {
408                                         error = 12;
409                                 }
410                         } else if (rtval[rtp + 4] == 14) {
411                                 jump = rtval[rtp + 3] & 0x38;
412                                 mask = 0x20;
413                                 if (get_sdld_target() == TARGET_ID_PDK) {
414                                         set_sdld_target(TARGET_ID_PDK14);
415                                 } else if (get_sdld_target() != TARGET_ID_PDK14) {
416                                         error = 13;
417                                 }
418                         } else if (rtval[rtp + 4] == 13) {
419                                 jump = rtval[rtp + 3] & 0x1C;
420                                 mask = 0x10;
421                                 if (get_sdld_target() == TARGET_ID_PDK) {
422                                         set_sdld_target(TARGET_ID_PDK13);
423                                 } else if (get_sdld_target() != TARGET_ID_PDK13) {
424                                         error = 14;
425                                 }
426 
427                                 /* T*SN and SET* instructions for PDK13 needed to
428                                  * be handled specially since their address is
429                                  * in between the opcode.
430                                  */
431                                 if ((rtval[rtp + 3] & 0x1F00) == 0x300 ||
432                                     (rtval[rtp + 3] & 0x1F00) == 0x200) {
433                                         rtval[rtp] <<= 1;
434                                 }
435                         }
436 
437                         const int icall =
438                             (mask >> 0) | (mask >> 1) | (mask >> 2);
439                         const int igoto = (mask >> 0) | (mask >> 1);
440                         if (((mode & R3_BYTE) && !(mode & R3_USGN)) ||
441                             jump == icall || jump == igoto) {
442                                 /* Addresses cannot be bigger than N - 1 bits.
443                                  * Any bits that are set past that point are
444                                  * marker bits that should be not shifted.
445                                  */
446                                 int marker = rtval[rtp + 1] & 0x80;
447                                 rtval[rtp + 1] &= ~0x80;
448 
449                                 rtval[rtp] /= 2;
450                                 rtval[rtp] |= (rtval[rtp + 1] & 1) << 7;
451                                 rtval[rtp + 1] /= 2;
452                                 rtval[rtp + 1] |= marker;
453                         }
454 
455                         const int inst = (rtval[rtp + 3] << 8) | rtval[rtp + 2];
456 
457                         /* Do the actual opcode fusion and ignore the two
458                          * bytes taken for the opcode by the assembler.
459                          */
460                         if (IS_R_J11(mode)) {
461                                 rtval[rtp + 2] |= rtval[rtp];
462                                 rtval[rtp + 3] |= rtval[rtp + 1];
463                         } else if (mode & R3_MSB) {
464                                 rtval[rtp + 2] |= rtval[rtp + 1];
465                                 rtval[rtp] = rtval[rtp + 1];
466                                 rtval[rtp + 1] = 0;
467                         } else {
468                                 rtval[rtp + 2] |= rtval[rtp];
469                                 rtval[rtp + 1] = 0;
470                         }
471 
472                         const int addr = (rtval[rtp + 1] << 8) | rtval[rtp];
473                         static int errorCount = 0;
474                         if (vpdkinst(inst, addr, rtval[rtp + 4])) {
475                                 if (errorCount < 3) {
476                                         error = 11;
477                                 } else if (errorCount == 3) {
478                                         puts("?ASlink-Warning-More instruction address errors omitted");
479                                 }
480                                 ++errorCount;
481                         }
482 
483                         mode &= ~R3_USGN;
484                         rtflg[rtp] = 0;
485                         rtflg[rtp + 1] = 0;
486                         rtflg[rtp + 4] = 0;
487                         rtofst += 3;
488                 }
489 
490                 /*
491                  * R3_BYTE or R3_WORD operation
492                  */
493                 else if (mode & R3_BYTE) {
494                         if (mode & R_BYT3)
495                         {
496                                 /* This is a three byte address, of which
497                                  * we will select one byte.
498                                  */
499 /* sdld specific */
500                                 if (mode & R_BIT)
501                                 {
502                                         relv = adb_24_bit(reli, rtp);
503                                 }
504 /* sdld specific */
505                                 else if (mode & R_HIB)
506                                 {
507                                         /* printf("24 bit address selecting hi byte.\n"); */
508                                         relv = adb_24_hi(reli, rtp);
509                                 }
510                                 else if (mode & R3_MSB)
511                                 {
512                                         /* Note that in 24 bit mode, R3_MSB
513                                          * is really the middle byte, not
514                                          * the most significant byte.
515                                          *
516                                          * This is ugly and I can only apologize
517                                          * for any confusion.
518                                          */
519                                         /* printf("24 bit address selecting middle byte.\n"); */
520                                         relv = adb_24_mid(reli, rtp);
521                                 }
522                                 else
523                                 {
524                                         /* printf("24 bit address selecting lo byte.\n"); */
525                                         relv = adb_24_lo(reli, rtp);
526                                 }
527                         }
528                         else if (mode & R3_BYTX) {
529                                 /* This is a two byte address, of
530                                  * which we will select one byte.
531                                  */
532                                 if (mode & R_BIT) {
533                                         relv = adb_bit(reli, rtp);
534                                 } else if (mode & R3_MSB) {
535                                         relv = adb_hi(reli, rtp);
536                                 } else {
537                                         relv = adb_lo(reli, rtp);
538                                 }
539                         } else {
540                                 relv = adb_1b(reli, rtp);
541                         }
542                 } else if (IS_R_J11(mode)) {
543                         /*
544                          * JLH: 11 bit jump destination for 8051.
545                          * Forms two byte instruction with
546                          * op-code bits in the MIDDLE!
547                          * rtp points at 3 byte locus:
548                          * first two will get the address,
549                          * third one has raw op-code
550                         */
551 
552                         /*
553                          * Calculate absolute destination
554                          * relv must be on same 2K page as pc
555                         */
556                         relv = adb_2b(reli, rtp);
557 
558                         if ((relv & ~((a_uint) 0x000007FF)) !=
559                             ((pc + rtp - rtofst) & ~((a_uint) 0x000007FF))) {
560                                         error = 6;
561                         }
562 
563                         /*
564                          * Merge MSB with op-code,
565                          * ignoring top 5 bits of address.
566                          * Then hide the op-code.
567                         */
568                         rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2];
569                         rtflg[rtp + 2] = 0;
570                         rtofst += 1;
571                 }
572                 else if (IS_R_J19(mode)) {
573                         /*
574                          * BK: 19 bit jump destination for DS80C390.
575                          * Forms four byte instruction with
576                          * op-code bits in the MIDDLE!
577                          * rtp points at 4 byte locus:
578                          * first three will get the address,
579                          * fourth one has raw op-code
580                          */
581                         relv = adb_3b(reli, rtp);
582 
583                         /*
584                          * Calculate absolute destination
585                          *  relv must be on same 512K page as pc
586                         */
587                         if ((relv & ~((a_uint) 0x0007FFFF)) !=
588                             ((pc + rtp - rtofst) & ~((a_uint) 0x0007FFFF))) {
589                                 error = 7;
590                         }
591 
592                         /*
593                          * Merge MSB with op-code,
594                          * ignoring top 5 bits of address.
595                          * Then hide the op-code.
596                         */
597                         rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3];
598                         rtflg[rtp + 3] = 0;
599                         rtofst += 1;
600                 }
601                 else if (IS_C24(mode))
602                 {
603                         /*
604                          * 24 bit destination
605                          */
606                         relv = adb_3b(reli, rtp);
607                         }
608                 else
609                 {
610                         /* 16 bit address. */
611                         relv = adb_2b(reli, rtp);
612                 }
613 
614                 /*
615                  * R3_BYTE with R3_BYTX offset adjust
616                  */
617                 if (mode & R3_BYTE) {
618                         if (mode & R3_BYTX) {
619                                 rtofst += (a_bytes - 1);
620                         }
621                 }
622 
623                 /*
624                  * Unsigned Byte Checking
625                  */
626                 if (mode & R3_USGN && mode & R3_BYTE && relv & ~((a_uint) 0x000000FF))
627                         error = 1;
628 
629                 /*
630                  * PCR Relocation Error Checking
631                  */
632                 if (mode & R3_PCR && mode & R3_BYTE) {
633                         r = relv & ~0x7F;
634                         if (r != (a_uint) ~0x7F && r != 0)
635                                 error = 2;
636                 }
637 
638                 /*
639                  * Page Relocation Error Checking
640                  */
641                 if ((TARGET_IS_GB || TARGET_IS_Z80) &&
642                         mode & R3_PAG0 && (relv & ~0xFF || paga || pags))
643                         error = 4;
644                 if (mode & R3_PAG  && (relv & ~0xFF))
645                         error = 5;
646 /* sdld specific */
647                 if ((mode & R_BIT) && (relv & ~0x87FF))
648                         error = 10;
649 /* end sdld specific */
650 
651                 /*
652                  * Error Processing
653                  */
654                 if (error) {
655                         rerr.aindex = aindex;
656                         rerr.mode = mode;
657                         rerr.rtbase = rtbase + rtp - rtofst - 1;
658                         rerr.rindex = rindex;
659                         rerr.rval = relv - reli;
660                         relerr3(errmsg3[error]);
661 
662                         for (i=rtp; i<rtp+a_bytes; i++) {
663                                 if (rtflg[i]) {
664                                         rterr[i] = error;
665                                         break;
666                                 }
667                         }
668                 }
669         }
670         if (uflag != 0) {
671                 lkulist(1);
672         }
673         if (oflag != 0) {
674                 lkout(1);
675         }
676 }
677 
678 char *errmsg3[] = {
679 /* 0 */ "LKRLOC3 Error List",
680 /* 1 */ "Unsigned Byte error",
681 /* 2 */ "Byte PCR relocation error",
682 /* 3 */ "",
683 /* 4 */ "Page0 relocation error",
684 /* 5 */ "Page Mode relocation error",
685 /* 6 */ "2K Page relocation error",
686 /* 7 */ "512K Page relocation error",
687 /* 8 */ "",
688 /* 9 */ "",
689 /* sdld specific */
690 /* 10 */        "Bit-addressable relocation error",
691 /* 11 */        "Invalid address for instruction",
692 /* 12 */        "mismatched pdk targets; expected pdk15",
693 /* 13 */        "mismatched pdk targets; expected pdk14",
694 /* 14 */        "mismatched pdk targets; expected pdk13"
695 /* end sdld specific */
696 };
697 
698 
699 /*)Function VOID        relp3()
700  *
701  *      The function relp3() evaluates a P line read by
702  *      the linker.  The P line data is combined with the
703  *      previous T line data to set the base page address
704  *      and test the paging boundary and length.
705  *
706  *              P Line
707  *
708  *              P 0 0 nn nn n1 n2 xx xx
709  *
710  *      The P line provides the paging information to the linker as
711  *      specified by a .setdp directive.  The format of the relocation
712  *      information is identical to that of the R line.  The correspond-
713  *      ing T line has the following information:
714  *              T xx xx aa aa bb bb
715  *
716  *      Where aa aa is the area reference number which specifies the
717  *      selected page area and bb bb is the base address of the page.
718  *      bb bb will require relocation processing if the 'n1 n2 xx xx' is
719  *      specified in the P line.  The linker will verify that the base
720  *      address is on a 256 byte boundary and that the page length of an
721  *      area defined with the PAG type is not larger than 256 bytes.
722  *
723  *      local variable:
724  *              areax   **a             pointer to array of area pointers
725  *              int aindex              area index
726  *              int mode                relocation mode
727  *              a_uint  relv    relocation value
728  *              int rindex              symbol / area index
729  *              int rtp                 index into T data
730  *              sym **s                 pointer to array of symbol pointers
731  *
732  *      global variables:
733  *              head *hp                pointer to the head structure
734  *              int lkerr               error flag
735  *              sdp sdp                 base page structure
736  *              FILE *stderr    standard error device
737  *
738  *      called functions:
739  *              a_uint adb_2b() lkrloc.c
740  *              a_uint evword() lkrloc.c
741  *              int eval()              lkeval.c
742  *              int fprintf()   c_library
743  *              int more()              lklex.c
744  *              int symval()    lksym.c
745  *
746  *      side effects:
747  *              The P and T lines are combined to set
748  *              the base page address and report any
749  *              paging errors.
750  *
751  */
752 
753 VOID
relp3()754 relp3()
755 {
756         int aindex, rindex;
757         int mode, rtp;
758         a_uint relv;
759         struct areax **a;
760         struct sym **s;
761 
762         /*
763          * Get area and symbol lists
764          */
765         a = hp->a_list;
766         s = hp->s_list;
767 
768         /*
769          * Verify Area Mode
770          */
771         if (eval() != (R3_WORD | R3_AREA) || eval()) {
772                 fprintf(stderr, "P input error\n");
773                 lkerr++;
774         }
775 
776         /*
777          * Get area pointer
778          */
779         aindex = (int) evword();
780         if (aindex >= hp->h_narea) {
781                 fprintf(stderr, "P area error\n");
782                 lkerr++;
783                 return;
784         }
785 
786         /*
787          * Do remaining relocations
788          */
789         while (more()) {
790                 mode = (int) eval();
791                 rtp = (int) eval();
792                 rindex = (int) evword();
793 
794                 /*
795                  * R3_SYM or R3_AREA references
796                  */
797                 if (mode & R3_SYM) {
798                         if (rindex >= hp->h_nsym) {
799                                 fprintf(stderr, "P symbol error\n");
800                                 lkerr++;
801                                 return;
802                         }
803                         relv = symval(s[rindex]);
804                 } else {
805                         if (rindex >= hp->h_narea) {
806                                 fprintf(stderr, "P area error\n");
807                                 lkerr++;
808                                 return;
809                         }
810                         relv = a[rindex]->a_addr;
811                 }
812                 adb_2b(relv, rtp);
813         }
814 
815         /*
816          * Paged values
817          */
818         aindex = (int) adb_2b(0, 2);
819         if (aindex >= hp->h_narea) {
820                 fprintf(stderr, "P area error\n");
821                 lkerr++;
822                 return;
823         }
824         sdp.s_areax = a[aindex];
825         sdp.s_area = sdp.s_areax->a_bap;
826         sdp.s_addr = adb_2b(0, 4);
827         if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF)
828                 relerp3("Page Definition Boundary Error");
829 }
830 
831 /*)Function VOID        rele3()
832  *
833  *      The function rele3() closes all open output files
834  *      at the end of the linking process.
835  *
836  *      local variable:
837  *              none
838  *
839  *      global variables:
840  *              int oflag               output type flag
841  *              int uflag               relocation listing flag
842  *
843  *      called functions:
844  *              VOID    lkfclose()      lkbank.c
845  *              VOID    lkflush()       lkout.c
846  *              VOID    lkulist()       lklist.c
847  *
848  *      side effects:
849  *              All open output files are closed.
850  *
851  */
852 
853 VOID
rele3()854 rele3()
855 {
856         if (uflag != 0) {
857                 lkulist(0);
858         }
859         if (oflag != 0) {
860                 lkflush();
861                 lkfclose();
862         }
863 }
864 
865 /*)Function VOID        relerr3(str)
866  *
867  *              char    *str            error string
868  *
869  *      The function relerr3() outputs the error string to
870  *      stderr and to the map file (if it is open).
871  *
872  *      local variable:
873  *              none
874  *
875  *      global variables:
876  *              FILE    *mfp            handle for the map file
877  *
878  *      called functions:
879  *              VOID    errdmp3()       lkrloc3.c
880  *
881  *      side effects:
882  *              Error message inserted into map file.
883  *
884  */
885 
886 VOID
relerr3(char * str)887 relerr3(char *str)
888 {
889         errdmp3(stderr, str);
890         if (mfp)
891                 errdmp3(mfp, str);
892 }
893 
894 /*)Function VOID        errdmp3(fptr, str)
895  *
896  *              FILE    *fptr           output file handle
897  *              char    *str            error string
898  *
899  *      The function errdmp3() outputs the error string str
900  *      to the device specified by fptr.  Additional information
901  *      is output about the definition and referencing of
902  *      the symbol / area error.
903  *
904  *      local variable:
905  *              int mode                error mode
906  *              int aindex              area index
907  *              int lkerr               error flag
908  *              int rindex              error index
909  *              sym **s         pointer to array of symbol pointers
910  *              areax   **a             pointer to array of area pointers
911  *              areax   *raxp           error area extension pointer
912  *
913  *      global variables:
914  *              sdp sdp         base page structure
915  *
916  *      called functions:
917  *              int fprintf()   c_library
918  *              VOID    prntval()       lkrloc.c
919  *
920  *      side effects:
921  *              Error reported.
922  *
923  */
924 
925 const char errdmp3_null_srcname[] = "<missing>";
926 
927 VOID
errdmp3(FILE * fptr,char * str)928 errdmp3(FILE *fptr, char *str)
929 {
930         int mode, aindex, rindex;
931         struct sym **s;
932         struct areax **a;
933         struct areax *raxp;
934 
935         a = hp->a_list;
936         s = hp->s_list;
937 
938         mode = rerr.mode;
939         aindex = rerr.aindex;
940         rindex = rerr.rindex;
941 
942         /*
943          * Print Error
944          */
945         fprintf(fptr, "\n?ASlink-Warning-%s", str);
946         lkerr++;
947 
948         /*
949          * Print symbol if symbol based
950          */
951         if (mode & R3_SYM) {
952                 fprintf(fptr, " for symbol  %s\n",
953                         &s[rindex]->s_id[0]);
954         } else {
955                 fprintf(fptr, "\n");
956         }
957 
958         /*
959          * Print Ref Info
960          */
961 /*         11111111112222222222333333333344444444445555555555666666666677777*/
962 /*12345678901234567890123456789012345678901234567890123456789012345678901234*/
963 /*        |                 |                 |                 |           */
964         fprintf(fptr,
965 "         file              module            area              offset\n");
966         fprintf(fptr,
967 "  Refby  %-14.14s    %-14.14s    %-14.14s    ",
968                         (hp->h_lfile && hp->h_lfile->f_idp) ? hp->h_lfile->f_idp : errdmp3_null_srcname,
969                         &hp->m_id[0],
970                         &a[aindex]->a_bap->a_id[0]);
971         prntval(fptr, rerr.rtbase);
972 
973         /*
974          * Print Def Info
975          */
976         if (mode & R3_SYM) {
977                 raxp = s[rindex]->s_axp;
978         } else {
979                 raxp = a[rindex];
980         }
981 /*         11111111112222222222333333333344444444445555555555666666666677777*/
982 /*12345678901234567890123456789012345678901234567890123456789012345678901234*/
983 /*        |                 |                 |                 |           */
984         fprintf(fptr,
985 "  Defin  %-14.14s    %-14.14s    %-14.14s    ",
986                         (raxp->a_bhp->h_lfile && raxp->a_bhp->h_lfile->f_idp) ? raxp->a_bhp->h_lfile->f_idp : errdmp3_null_srcname,
987                         &raxp->a_bhp->m_id[0],
988                         &raxp->a_bap->a_id[0]);
989         if (mode & R3_SYM) {
990                 prntval(fptr, s[rindex]->s_addr);
991         } else {
992                 prntval(fptr, rerr.rval);
993         }
994 }
995 
996 /*)Function VOID        relerp3(str)
997  *
998  *              char    *str            error string
999  *
1000  *      The function relerp3() outputs the paging error string to
1001  *      stderr and to the map file (if it is open).
1002  *
1003  *      local variable:
1004  *              none
1005  *
1006  *      global variables:
1007  *              FILE    *mfp            handle for the map file
1008  *
1009  *      called functions:
1010  *              VOID    erpdmp3()       lkrloc3.c
1011  *
1012  *      side effects:
1013  *              Error message inserted into map file.
1014  *
1015  */
1016 
1017 VOID
relerp3(char * str)1018 relerp3(char *str)
1019 {
1020         erpdmp3(stderr, str);
1021         if (mfp)
1022                 erpdmp3(mfp, str);
1023 }
1024 
1025 /*)Function VOID        erpdmp3(fptr, str)
1026  *
1027  *              FILE    *fptr           output file handle
1028  *              char    *str            error string
1029  *
1030  *      The function erpdmp3() outputs the error string str
1031  *      to the device specified by fptr.
1032  *
1033  *      local variable:
1034  *              head    *thp            pointer to head structure
1035  *
1036  *      global variables:
1037  *              int             lkerr           error flag
1038  *              sdp             sdp                     base page structure
1039  *
1040  *      called functions:
1041  *              int fprintf()           c_library
1042  *              VOID    prntval()       lkrloc.c
1043  *
1044  *      side effects:
1045  *              Error reported.
1046  *
1047  */
1048 
1049 VOID
erpdmp3(FILE * fptr,char * str)1050 erpdmp3(FILE *fptr, char *str)
1051 {
1052         struct head *thp;
1053 
1054         thp = sdp.s_areax->a_bhp;
1055 
1056         /*
1057          * Print Error
1058          */
1059         fprintf(fptr, "\n?ASlink-Warning-%s\n", str);
1060         lkerr++;
1061 
1062         /*
1063          * Print PgDef Info
1064          */
1065 /*         111111111122222222223333333333444444444455555555556666666666777*/
1066 /*123456789012345678901234567890123456789012345678901234567890123456789012*/
1067         fprintf(fptr,
1068 "         file              module            pgarea            pgoffset\n");
1069         fprintf(fptr,
1070 "  PgDef  %-14.14s    %-14.14s    %-14.14s    ",
1071                         thp->h_lfile->f_idp,
1072                         &thp->m_id[0],
1073                         &sdp.s_area->a_id[0]);
1074         prntval(fptr, sdp.s_area->a_addr + sdp.s_addr);
1075 }
1076 
1077 /* sdld specific */
1078 /*)Function a_uint              adb_bit(v, i)
1079  *
1080  *              a_uint v        value to add to byte
1081  *              int i           rtval[] index
1082  *
1083  *      The function adb_bit() converts the single
1084  *      byte address value contained in rtval[i] to bit-
1085  *      addressable space and adds the value of v to it.
1086  *      The new value of rtval[i] is returned.
1087  *
1088  *      local variable:
1089  *              a_uint  j               temporary evaluation variable
1090  *
1091  *      global variables:
1092  *              none
1093  *
1094  *      called functions:
1095  *              none
1096  *
1097  *      side effects:
1098  *              The value of rtval[] is changed.
1099  *
1100  */
1101 
1102 a_uint
adb_bit(a_uint v,int i)1103 adb_bit(a_uint v, int i)
1104 {
1105         a_uint j;
1106 
1107         j = adb_lo(v, i) & 0xFF;
1108         if ((j >= 0x20) && (j <= 0x2F)) {
1109                 j = (j - 0x20) * 8;
1110         } else if ((j < 0x80) || ((j & 0x07) != 0)) {
1111                 return(0x100);//error
1112         }
1113 
1114         if (hilo) {
1115                 j = rtval[i+1] = j + (rtval[i] & 0x07);
1116         } else {
1117                 j = rtval[i] = j + (rtval[i+1] & 0x07);
1118         }
1119         return(j);
1120 }
1121 /* end sdld specific */
1122 
1123 /*)Function     a_uint  adb_lo(v, i)
1124  *
1125  *              int     v               value to add to byte
1126  *              int     i               rtval[] index
1127  *
1128  *      The function adb_lo() adds the value of v to the
1129  *      value contained in rtval[i] through rtval[i + a_bytes - 1].
1130  *      The new value of rtval[i] ... is returned.
1131  *      The rtflg[] flags are cleared for all rtval[i] ... except
1132  *      the LSB.
1133  *
1134  *      local variable:
1135  *              a_uint  j               temporary evaluation variable
1136  *
1137  *      global variables:
1138  *              hilo                    byte ordering parameter
1139  *
1140  *      called functions:
1141  *              none
1142  *
1143  *      side effects:
1144  *              The value of rtval[] is changed.
1145  *              The rtflg[] values corresponding to all bytes
1146  *              except the LSB of the value are cleared to reflect
1147  *              the fact that the LSB is the selected byte.
1148  *
1149  */
1150 
1151 a_uint
adb_lo(v,i)1152 adb_lo(v, i)
1153 a_uint  v;
1154 int     i;
1155 {
1156         a_uint j;
1157         int m, n;
1158 
1159         j = adb_xb(v, i);
1160         /*
1161          * LSB is lowest order byte of data
1162          */
1163         m = (hilo ? a_bytes-1 : 0);
1164         for (n=0; n<a_bytes; n++) {
1165                 if(n != m) rtflg[i+n] = 0;
1166         }
1167         return (j);
1168 }
1169 
1170 /*)Function     a_uint  adb_hi(v, i)
1171  *
1172  *              int     v               value to add to byte
1173  *              int     i               rtval[] index
1174  *
1175  *      The function adb_hi() adds the value of v to the
1176  *      value contained in rtval[i] through rtval[i + a_bytes - 1].
1177  *      The new value of rtval[i] .... is returned.
1178  *      The LSB rtflg[] is cleared.
1179  *
1180  *      local variable:
1181  *              a_uint  j               temporary evaluation variable
1182  *
1183  *      global variables:
1184  *              hilo                    byte ordering parameter
1185  *
1186  *      called functions:
1187  *              none
1188  *
1189  *      side effects:
1190  *              The value of rtval[] is changed.
1191  *              The rtflg[] values corresponding to all bytes
1192  *              except the 2nd byte (MSB) are cleared to reflect
1193  *              the fact that the MSB is the selected byte.
1194  *
1195  */
1196 
1197 a_uint
adb_hi(v,i)1198 adb_hi(v, i)
1199 a_uint  v;
1200 int     i;
1201 {
1202         a_uint j;
1203         int m, n;
1204 
1205         j = adb_xb(v, i);
1206         /*
1207          * MSB is next lowest order byte of data
1208          */
1209         m = (hilo ? a_bytes-2 : 1);
1210         for (n=0; n<a_bytes; n++) {
1211                 if(n != m) rtflg[i+n] = 0;
1212         }
1213         return (j);
1214 }
1215 
1216 /* sdld specific */
1217 /*)Function a_uint              adb_24_bit(v, i)
1218  *
1219  *              a_uint v        value to add to byte
1220  *              int i           rtval[] index
1221  *
1222  *      The function adb_24_bit() converts the single
1223  *      byte address value contained in rtval[i] to bit-
1224  *      addressable space and adds the value of v to it.
1225  *      The new value of rtval[i] is returned.
1226  *
1227  *      local variable:
1228  *              a_uint  j               temporary evaluation variable
1229  *
1230  *      global variables:
1231  *              none
1232  *
1233  *      called functions:
1234  *              none
1235  *
1236  *      side effects:
1237  *              The value of rtval[] is changed.
1238  *
1239  */
1240 
1241 a_uint
adb_24_bit(v,i)1242 adb_24_bit(v, i)
1243 a_uint v;
1244 int i;
1245 {
1246         a_uint j;
1247 
1248         j = adb_24_lo(v, i) & 0xFF;
1249         if ((j >= 0x20) && (j <= 0x2F)) {
1250                 j = (j - 0x20) * 8;
1251         } else if ((j < 0x80) || ((j & 0x07) != 0)) {
1252                 return(0x100);//error
1253         }
1254 
1255         if (hilo) {
1256                 j = rtval[i+2] = j + (rtval[i+1] & 0x07);
1257         } else {
1258                 j = rtval[i] = j + (rtval[i+1] & 0x07);
1259         }
1260         return(j);
1261 }
1262 
1263 /*)Function a_uint              adb_24_hi(v, i)
1264  *
1265  *              a_uint v        value to add to byte
1266  *              int i           rtval[] index
1267  *
1268  *      The function adb_24_hi() adds the value of v to the
1269  *      24 bit value contained in rtval[i] - rtval[i+2].
1270  *      The new value of rtval[i] / rtval[i+1] is returned.
1271  *      The LSB & middle byte rtflg[] is cleared.
1272  *
1273  *      local variable:
1274  *              a_uint  j               temporary evaluation variable
1275  *
1276  *      global variables:
1277  *              hilo                    byte ordering parameter
1278  *
1279  *      called functions:
1280  *              none
1281  *
1282  *      side effects:
1283  *              The value of rtval[] is changed.
1284  *              The rtflg[] value corresponding to the
1285  *              LSB & middle byte of the word value is cleared to
1286  *              reflect the fact that the MSB is the selected byte.
1287  *
1288  */
1289 
1290 a_uint
adb_24_hi(v,i)1291 adb_24_hi(v, i)
1292 a_uint v;
1293 int i;
1294 {
1295         a_uint j;
1296 
1297         j = adb_3b(v, i);
1298 
1299         /* Remove the lower two bytes. */
1300         if (hilo)
1301         {
1302                 rtflg[i+2] = 0;
1303         }
1304         else
1305         {
1306                 rtflg[i] = 0;
1307         }
1308         rtflg[i+1] = 0;
1309 
1310         return (j);
1311 }
1312 
1313 /*)Function a_uint              adb_24_mid(v, i)
1314  *
1315  *              a_uint v        value to add to byte
1316  *              int i           rtval[] index
1317  *
1318  *      The function adb_24_mid() adds the value of v to the
1319  *      24 bit value contained in rtval[i] - rtval[i+2].
1320  *      The new value of rtval[i] / rtval[i+1] is returned.
1321  *      The LSB & MSB byte rtflg[] is cleared.
1322  *
1323  *      local variable:
1324  *              a_uint  j               temporary evaluation variable
1325  *
1326  *      global variables:
1327  *              hilo                    byte ordering parameter
1328  *
1329  *      called functions:
1330  *              none
1331  *
1332  *      side effects:
1333  *              The value of rtval[] is changed.
1334  *              The rtflg[] value corresponding to the
1335  *              LSB & MSB of the 24 bit value is cleared to reflect
1336  *              the fact that the middle byte is the selected byte.
1337  *
1338  */
1339 
1340 a_uint
adb_24_mid(v,i)1341 adb_24_mid(v, i)
1342 a_uint v;
1343 int i;
1344 {
1345         a_uint j;
1346 
1347         j = adb_3b(v, i);
1348 
1349         /* remove the MSB & LSB. */
1350         rtflg[i+2] = 0;
1351         rtflg[i] = 0;
1352 
1353         return (j);
1354 }
1355 
1356 /*)Function a_uint              adb_24_lo(v, i)
1357  *
1358  *              a_uint v        value to add to byte
1359  *              int i           rtval[] index
1360  *
1361  *      The function adb_24_lo() adds the value of v to the
1362  *      24 bit value contained in rtval[i] - rtval[i+2].
1363  *      The new value of rtval[i] / rtval[i+1] is returned.
1364  *      The MSB & middle byte rtflg[] is cleared.
1365  *
1366  *      local variable:
1367  *              a_uint  j               temporary evaluation variable
1368  *
1369  *      global variables:
1370  *              hilo                    byte ordering parameter
1371  *
1372  *      called functions:
1373  *              none
1374  *
1375  *      side effects:
1376  *              The value of rtval[] is changed.
1377  *              The rtflg[] value corresponding to the
1378  *              MSB & middle byte  of the word value is cleared to
1379  *              reflect the fact that the LSB is the selected byte.
1380  *
1381  */
1382 
1383 a_uint
adb_24_lo(v,i)1384 adb_24_lo(v, i)
1385 a_uint v;
1386 int i;
1387 {
1388         a_uint j;
1389 
1390         j = adb_3b(v, i);
1391 
1392         /* Remove the upper two bytes. */
1393         if (hilo)
1394         {
1395                 rtflg[i] = 0;
1396         }
1397         else
1398         {
1399                 rtflg[i+2] = 0;
1400         }
1401         rtflg[i+1] = 0;
1402 
1403         return (j);
1404 }
1405 
1406 /*)Function VOID              vpdkinst(inst, addr, ver)
1407  *
1408  *              int inst        instruction
1409  *              int addr        address
1410  *              int ver         PDK version
1411  *
1412  *      The function vpdkinst() tests whether the address
1413  *      does not exceed the allowed maximum size of the
1414  *      instruction.
1415  *
1416  *      local variable:
1417  *              a_uint  j               temporary evaluation variable
1418  *
1419  *      global variables:
1420  *              hilo                    byte ordering parameter
1421  *
1422  *      called functions:
1423  *              none
1424  *
1425  *      side effects:
1426  *              The value of rtval[] is changed.
1427  *              The rtflg[] value corresponding to the
1428  *              MSB & middle byte  of the word value is cleared to
1429  *              reflect the fact that the LSB is the selected byte.
1430  *
1431  */
1432 
1433 int
vpdkinst(inst,addr,ver)1434 vpdkinst(inst, addr, ver)
1435 int inst;
1436 int addr;
1437 int ver;
1438 {
1439         switch (ver) {
1440         case 13: /* PDK 13 */
1441                 switch (inst & 0x1C00) {
1442                 case 0x1800:
1443                 case 0x1C00:
1444                         if (addr > 0x3FF) {
1445                                 return 1;
1446                         }
1447                         break;
1448                 case 0x1000:
1449                 case 0x1400:
1450                         if (addr > 0xFF) {
1451                                 return 1;
1452                         }
1453                         break;
1454                 case 0x0C00:
1455                 case 0x2000:
1456                         if (addr > 0x1F) {
1457                                 return 1;
1458                         }
1459                         break;
1460                 case 0x800:
1461                 case 0x400:
1462                         if (addr > 0x3F) {
1463                                 return 1;
1464                         }
1465                         break;
1466                 case 0x0:
1467                         if (inst & 0x200) {
1468                                 /* Address was right shifted to fit into the
1469                                  * opcode.
1470                                  */
1471                                 if ((addr >> 1) > 0xF) {
1472                                         return 1;
1473                                 }
1474                         } else if (inst & 0x100) {
1475                                 if (addr > 0xFF) {
1476                                         return 1;
1477                                 }
1478                         } else if (addr > 0x1F) {
1479                                 return 1;
1480                         }
1481                         break;
1482                 }
1483                 break;
1484         case 14: /* PDK 14 */
1485                 switch (inst & 0x3800) {
1486                 case 0x3000:
1487                 case 0x3800:
1488                         if (addr > 0x7FF) {
1489                                 return 1;
1490                         }
1491                         break;
1492                 case 0x2800:
1493                         if (addr > 0xFF) {
1494                                 return 1;
1495                         }
1496                         break;
1497                 case 0x1800:
1498                 case 0x2000:
1499                         if (addr > 0x3F) {
1500                                 return 1;
1501                         }
1502                         break;
1503                 case 0x800:
1504                 case 0x1000:
1505                         if (addr > 0x7F) {
1506                                 return 1;
1507                         }
1508                         break;
1509                 case 0x0:
1510                         if (inst & 0x400) {
1511                                 if (addr > 0x3F) {
1512                                         return 1;
1513                                 }
1514                         } else if ((inst & 0x300) == 0x300) {
1515                                 if (addr & 0x1) {
1516                                         return 1;
1517                                 }
1518                         } else if ((inst & 0x300) == 0x200 && addr > 0xFF) {
1519                                 return 1;
1520                         } else if ((inst & 0x300) == 0x100 && addr > 0x3F) {
1521                                 return 1;
1522                         }
1523                         break;
1524                 }
1525                 break;
1526         case 15: /* PDK 15 */
1527                 switch (inst & 0x7000) {
1528                 case 0x6000:
1529                 case 0x7000:
1530                         if (addr > 0xFFF) {
1531                                 return 1;
1532                         }
1533                         break;
1534                 case 0x5000:
1535                         if (inst & 0x800) {
1536                                 if (addr > 0x7F) {
1537                                         return 1;
1538                                 }
1539                                 break;
1540                         }
1541                 case 0x1000:
1542                 case 0x2000:
1543                         if (addr > 0xFF) {
1544                                 return 1;
1545                         }
1546                         break;
1547                 case 0x3000:
1548                 case 0x4000:
1549                         if (addr > 0x7F) {
1550                                 return 1;
1551                         }
1552                         break;
1553                 case 0x0:
1554                         switch (inst & 0xC00) {
1555                         case 0xC00:
1556                                 if (addr > 0xFF) {
1557                                         return 1;
1558                                 }
1559                                 break;
1560                         case 0x400:
1561                                 if (addr > 0xFF || (addr & 0x1)) {
1562                                         return 1;
1563                                 }
1564                                 break;
1565                         case 0x0:
1566                                 if ((inst & 0x200) && addr > 0xFF) {
1567                                         return 1;
1568                                 } else if (!(inst & 0x200) && addr > 0x7F) {
1569                                         return 1;
1570                                 }
1571                                 break;
1572                         }
1573                         break;
1574                 }
1575                 break;
1576         }
1577         return 0;
1578 #undef MASK
1579 }
1580 
1581 /* end sdld specific */
1582