C6474 required changes
[keystone-rtos/ibl.git] / src / interp / coff / cload.c
1 /***************************************************************************
2 * FILENAME: cload.c
3 * VERSION:  2.6  5/2/96  13:11:03
4 * SCCS ID:  "@(#)cload.c        2.6  5/2/96"
5 ***************************************************************************/
6 /******************************************************************************/
7 /* CLOAD.C  - Generic COFF Loader                      Version 6.00 4/96      */
8 /******************************************************************************/
9 /*                                                                            */
10 /*  This module contains functions to read in and load a COFF object file.    */
11 /*  The following routines are defined here:                                  */
12 /*                                                                            */
13 /*    cload()           - Main driver for COFF loader.                        */
14 /*    cload_headers()   - Read in the various headers of the COFF file.       */
15 /*    cload_data()      - Read in the raw data and load it into memory.       */
16 /*    cload_sect_data() - Read, relocate, and write out one section.          */
17 /*    cload_cinit()     - Process one buffer of C initialization records.     */
18 /*    cload_symbols()   - Read in the symbol table.                           */
19 /*    cload_strings()   - Read in the string table.                           */
20 /*    str_free()        - Free a string table.                                */
21 /*    sym_read()        - Read and relocate a symbol and its aux entry.       */
22 /*    sym_name()        - Return a pointer to the name of a symbol.           */
23 /*    sym_add_name()    - Add a symbol name to the string table.              */
24 /*    reloc_add()       - Add a symbol to the relocation symbol table.        */
25 /*    relocate()        - Perform a single relocation.                        */
26 /*    reloc_read()      - Read in and swap one relocation entry.              */
27 /*    reloc_size()      - Return the field size of a relocation type.         */
28 /*    reloc_offset()    - Return the field offset of a relocation type.       */
29 /*    reloc_stop()      - Return the number of bits to read for a reloc type. */
30 /*    sym_reloc_amount()- Return relocation amount for a relocation entry.    */
31 /*    unpack()          - Extract a relocation field from object bytes.       */
32 /*    repack()          - Encode a relocated field into object bytes.         */
33 /*    cload_lineno()    - Read in & swap line number entries.                 */
34 /*    swap4byte()       - Swap the order of bytes in a int.                  */
35 /*    swap2byte()       - Swap the order of bytes in a short.                 */
36 /*                                                                            */
37 /*  The loader calls the following external functions to perform application  */
38 /*  specific tasks:                                                           */
39 /*                                                                            */
40 /*   set_reloc_amount() - Define relocation amounts for each section.         */
41 /*   mem_write()        - Load a buffer of data into memory.                  */
42 /*   lookup_sym()       - Look up a symbol in an external symbol table.       */
43 /*   load_syms()        - Build the symbol table for the application.         */
44 /*   load_msg()         - Write diagnostic messages during loading.           */
45 /*                                                                            */
46 /******************************************************************************/
47 #include "header.h"
48 #include "coff_trg.h"
49 #if ((FILE_BASED) && !defined(FILE))
50 #include <stdio.h>
51 #endif
52 /*----------------------------------------------------------------------------*/
53 /* CONSTANTS, MACROS, VARIABLES, AND STRUCTURES FOR THE LOADER.               */
54 /*----------------------------------------------------------------------------*/
55 #define TRUE 1
56 #define FALSE 0
57 #define WORDSZ sizeof(T_DATA)           /* SIZE OF DATA UNITS IN OBJ FILE     */
59 #ifdef TMS320C60
60    extern int target_coff (unsigned short flags);
61 #endif
63 /*----------------------------------------------------------------------------*/
64 /* APPLICATION VARIABLES                                                      */
65 /*----------------------------------------------------------------------------*/
66 #if (FILE_BASED)
67 FILE   *fin;                                                    /* INPUT FILE                         */
68 #else
69 extern unsigned char gRxBuffer[0x400040];
70 #endif
71                             
72 int     need_data    = TRUE;            /* APPLICATION NEEDS RAW DATA         */
73 int     need_symbols = FALSE;           /* APPLICATION NEEDS SYMBOL TABLE     */
74 int     clear_bss    = FALSE;           /* CLEAR BSS SECTION                  */
77 /*----------------------------------------------------------------------------*/
78 /* FILL VALUES TO BE USED BY LOADERS                                          */
79 /*----------------------------------------------------------------------------*/
80 #if defined(OTIS)
81 extern int fill_bss;
82 extern int fill_bss_value;
83 #else
84 #define fill_bss 0
85 #define fill_bss_value 0
86 #endif
88 /*----------------------------------------------------------------------------*/
89 /* LOADER VARIABLES                                                           */
90 /*----------------------------------------------------------------------------*/
91 FILHDR  file_hdr;                       /* FILE HEADER STRUCTURE              */
92 int     coff_version;                   /* COFF VERSION USED IN FILE          */
93 AOUTHDR o_filehdr;                      /* OPTIONAL (A.OUT) FILE HEADER       */
94 T_ADDR  entry_point;                    /* ENTRY POINT OF MODULE              */
95 T_ADDR *reloc_amount = NULL;            /* AMOUNT OF RELOCATION PER SECTION   */
96 char   *sect_hdrs = NULL;               /* ARRAY OF SECTION HEADERS           */
97 char   *o_sect_hdrs = NULL;             /* ARRAY OF OLD COFF SECTION HEADERS  */
98 int     n_sections;                     /* NUMBER OF SECTIONS IN THE FILE     */
99 int     big_e_target;                   /* TARGET DATA IN BIG-ENDIAN FORMAT   */
100 int     byte_swapped;                   /* BYTE ORDERING OPPOSITE OF HOST     */
101 int     curr_sect;                      /* SECTION NUMBER CURRENTLY LOADING   */
102 int     load_err;                       /* ERROR CODE RETURNED IF LOADER FAILS*/
103 struct strtab *str_head = NULL;         /* LIST OF STRING TABLE BUFFERS       */
105 static T_SIZE  init_size = 0;           /* CURRENT SIZE OF C INITIALIZATION   */
106 static int     need_reloc;              /* RELOCATION REQUIRED                */
108 #if TMS320C60
109 int big_e_config = TRG_DEF_BIG_E;       /* ENDIANNESS CONFIGURATION           */
110 #else
111 int big_e_config = DONTCARE;            /* ENDIANNESS CONFIGURATION           */
112 #endif
114 /*----------------------------------------------------------------------------*/
115 /* THIS STRUCTURE IS USED TO STORE THE RELOCATION AMOUNTS FOR SYMBOLS.        */
116 /* EACH RELOCATABLE SYMBOL HAS A CORRESPONDING ENTRY IN THIS TABLE.           */
117 /* THE TABLE IS SORTED BY SYMBOL INDEX; LOOKUP USES A BINARY SEARCH.          */
118 /*----------------------------------------------------------------------------*/
119 typedef struct
121    int rt_index;                       /* INDEX OF SYMBOL IN SYMBOL TABLE    */
122    int rt_disp;                        /* AMOUNT OF RELOCATION               */
123 } RELOC_TAB;
125 /*----------------------------------------------------------------------------*/
126 /* THE RELOCATION SYMBOL TABLE IS ALLOCATED DYNAMICALLY, AND REALLOCATED      */
127 /* AS MORE SPACE IS NEEDED.                                                   */
128 /*----------------------------------------------------------------------------*/
129 #define RELOC_TAB_START 128             /* STARTING SIZE OF TABLE             */
130 #define RELOC_GROW_SIZE 128             /* REALLOC AMOUNT FOR TABLE           */
132 static RELOC_TAB *reloc_tab = NULL;     /* RELOCATION SYMBOL TABLE            */
134 static int        reloc_tab_size;       /* CURRENT ALLOCATED AMOUNT           */
135 static int        reloc_sym_index;      /* CURRENT SIZE OF TABLE              */
137 /*----------------------------------------------------------------------------*/
138 /* RUN-TIME RELOCATION (AS OPPOSED TO LOAD-TIME) RELOCATION IS DETERMINED     */
139 /* AS FOLLOWS:  IF THE SECTION'S RUNTIME ADDRESS == LOADTIME ADDRESS, USE     */
140 /* LOADTIME RELOCATION.  OTHERWISE, ASSUME LOADTIME RELOC ONLY (RUNTIME RELOC */
141 /* == 0).                                                                     */
142 /*----------------------------------------------------------------------------*/
143 #define RUN_RELOC_AMOUNT(i) ((SECT_HDR(i)->s_paddr == SECT_HDR(i)->s_vaddr) ?  \
144                                     reloc_amount[i] : 0)
146 /*----------------------------------------------------------------------------*/
147 /* DEFINE A STRUCTURE FOR STRING TABLE BUFFERS.  THESE BUFFERS ARE STORED     */
148 /* AS A LINKED LIST OF MEMORY PACKETS, EACH CONTAINING UP TO 64K OF THE       */
149 /* STRING TABLE.                                                              */
150 /*----------------------------------------------------------------------------*/
151 typedef struct strtab
153    unsigned int  size;                 /* SIZE OF THIS PACKET                */
154    unsigned int  offset;               /* STARTING OFFSET OF THIS PACKET     */
155    unsigned int  index;                /* AMOUNT CURRENTLY FILLED            */
156    struct strtab *next;                 /* NEXT BUFFER                        */
157    char           buf[1];               /* STRING DATA (EXPAND AS ALLOCATED)  */
158 } STRTAB;
160 #define MAX_STRING_ALLOC (unsigned int)(0xffff-sizeof(STRTAB)+1)
161                                        /* MAX STRING BUFFER: 64K (SMALL HOSTS)*/
162 #define MIN_STRING_ALLOC 0x0400        /* MIN STRING BUFFER: 1K               */
164 unsigned int unpack();
166 #define reloc_read(x)   TRUE
168 /* extern void mem_copy(unsigned char* dst, unsigned char* src, int nbytes); - defined in osal.h */
169 /******************************************************************************/
170 /*                                                                            */
171 /* CLOAD() - Main driver for COFF loader.                                     */
172 /*                                                                            */
173 /******************************************************************************/
174 int cload()
176    int result;
178    load_err = 0;
179    result   = cload_headers() && cload_data();
181    if (reloc_tab) free(reloc_tab);
182    reloc_tab = NULL;
184    if(result == TRUE)
185        return 0;
186    else
187        return -1;
190 \f
191 /******************************************************************************/
192 /*                                                                            */
193 /* CLOAD_HEADERS() - Read in the various headers of the COFF file.            */
194 /*                                                                            */
195 /******************************************************************************/
196 int cload_headers()
198    int i;
200    byte_swapped = FALSE;
201    need_reloc   = FALSE;
202 #if FILE_BASED
203    if (fseek(fin, 0L, 0) != 0 || !fread(&file_hdr, FILHSZ, 1, fin)) 
204       { load_err = E_FILE; return FALSE; }
205 #else
206         mem_copy((void*)&file_hdr, gRxBuffer, FILHSZ);
207 #endif
209    /*-------------------------------------------------------------------------*/
210    /* MAKE SURE THIS IS REALLY A COFF FILE. CHECK FOR SWAPPED FILES.          */
211    /* DETERMINE BYTE ORDERING OF OBJECT DATA.                                 */
212    /*-------------------------------------------------------------------------*/
213    if (!ISCOFF(file_hdr.f_magic))
214    {
215        swap2byte(&file_hdr.f_magic);
217        if (!ISCOFF(file_hdr.f_magic)) { load_err = E_MAGIC; return FALSE; }
219        byte_swapped = TRUE;
221        swap2byte(&file_hdr.f_nscns);  swap4byte(&file_hdr.f_timdat);
222        swap4byte(&file_hdr.f_symptr); swap4byte(&file_hdr.f_nsyms);
223        swap2byte(&file_hdr.f_opthdr); swap2byte(&file_hdr.f_flags);
224 #if COFF_VERSION_1 || COFF_VERSION_2
225        swap2byte(&file_hdr.f_target_id); 
226 #endif
227    }
229    /*-------------------------------------------------------------------------*/
230    /* DETERMINE THE ENDIANNESS OF THE COFF FILE, AND ENSURE THE ENDIANNESS OF */
231    /* THE FILE IS THE SAME AS THE TARGET, IF THERE IS A TARGET.               */
232    /*-------------------------------------------------------------------------*/
233    big_e_target = ((file_hdr.f_flags & F_BIG) != 0);
234    if (big_e_config != DONTCARE && big_e_target != big_e_config) 
235       { load_err = E_ENDIAN; return FALSE; }
237    /*-------------------------------------------------------------------------*/
238    /* DETERMINE VERSION OF COFF BEING USED, CHECK TARGET ID IF NEEDED.        */
239    /*-------------------------------------------------------------------------*/
240    if (ISCOFF_1(file_hdr.f_magic) || ISCOFF_2(file_hdr.f_magic))
241    {
242        if (!ISMAGIC(file_hdr.f_target_id)) { load_err = E_MAGIC; return FALSE; }
243        coff_version = file_hdr.f_magic;
244    } 
245    else coff_version = COFF_MAGIC_0;
247 #ifdef TMS320C60
248    /*-------------------------------------------------------------------------*/
249    /* DETERMINE WHETHER THE RIGHT COFF IS BEING LOADED                        */
250    /*-------------------------------------------------------------------------*/
251    if ( !target_coff( file_hdr.f_flags) )
252        { load_err = E_FILE; return FALSE; }
253 #endif
254  
255    /*-------------------------------------------------------------------------*/
256    /* READ IN OPTIONAL HEADER, IF THERE IS ONE, AND SWAP IF NEEDED.           */
257    /*-------------------------------------------------------------------------*/
258    if (file_hdr.f_opthdr == AOUTSZ)
259    {
260 #if FILE_BASED          
261       fseek(fin, (int)FILHSZ_IN(coff_version), 0); 
262       if (fread(&o_filehdr, file_hdr.f_opthdr, 1, fin) != 1) 
263          { load_err = E_FILE; return FALSE; }
264 #else
265         mem_copy((void*)&o_filehdr, &gRxBuffer[(int)FILHSZ_IN(coff_version)], file_hdr.f_opthdr);
266 #endif   
268       if (byte_swapped)
269       {
270           swap2byte(&o_filehdr.magic);      swap2byte(&o_filehdr.vstamp);
271           swap4byte(&o_filehdr.tsize);      swap4byte(&o_filehdr.dsize);
272           swap4byte(&o_filehdr.bsize);      swap4byte(&o_filehdr.entrypt);
273           swap4byte(&o_filehdr.text_start); swap4byte(&o_filehdr.data_start);
274       }
275       entry_point = o_filehdr.entrypt;
276    }
278    /*-------------------------------------------------------------------------*/
279    /* Read in string table so that we can see long section names, if needed.  */
280    /* This used tobe read right before the symbol table was read, but now the */
281    /* section headers use "flexname" method to specify section names and so   */
282    /* might need access to a string table entry.                              */
283    /*-------------------------------------------------------------------------*/
284    //if (!cload_strings()) return FALSE;
286    /*-------------------------------------------------------------------------*/
287    /* READ IN SECTION HEADERS.                                                */
288    /*-------------------------------------------------------------------------*/
289    if (sect_hdrs)   { free(sect_hdrs);     sect_hdrs = NULL; }
290    if (o_sect_hdrs) { free(o_sect_hdrs); o_sect_hdrs = NULL; }
292    if (!(sect_hdrs = (char *)malloc((n_sections = file_hdr.f_nscns) * SCNHSZ)))
293       { load_err = E_ALLOC;  return FALSE; }
294       
295 #if FILE_BASED
296    fseek(fin, (int)FILHSZ_IN(coff_version) + file_hdr.f_opthdr, 0); 
297 #endif
298    /*-------------------------------------------------------------------------*/
299    /* Depending on which version of COFF we are reading, set up the section   */
300    /* headers or s copy that we can translate into the new version.           */
301    /*-------------------------------------------------------------------------*/
302    if (ISCOFF_2(coff_version))
303    {
304 #if FILE_BASED
305       if (fread(sect_hdrs,SCNHSZ_IN(coff_version),n_sections,fin) != n_sections)
306          { load_err = E_FILE;   return FALSE; }
307 #else
308         mem_copy((void*)sect_hdrs, &gRxBuffer[(int)FILHSZ_IN(coff_version) + file_hdr.f_opthdr], SCNHSZ_IN(coff_version)*n_sections );
309 #endif
310    }
311    else
312    {
313       if (!(o_sect_hdrs = (char *)malloc(n_sections * SCNHSZ_IN(coff_version))))
314          { load_err = E_ALLOC;  return FALSE; }
315 #if FILE_BASED
316       if (fread(o_sect_hdrs,SCNHSZ_IN(coff_version),n_sections,fin)!=n_sections)
317          { load_err = E_FILE;   return FALSE; }
318 #else
319         mem_copy((void*)o_sect_hdrs, &gRxBuffer[(int)FILHSZ_IN(coff_version) + file_hdr.f_opthdr], SCNHSZ_IN(coff_version)*n_sections );
320 #endif
321    }
323    if (reloc_amount) free(reloc_amount);
325         if (!(reloc_amount = (T_ADDR*)malloc(n_sections * sizeof(T_ADDR))))
326         { 
327         load_err = E_ALLOC;  
328         return FALSE; 
329         }
331    /*-------------------------------------------------------------------------*/
332    /* SWAP SECTION HEADERS IF REQUIRED.                                       */
333    /*-------------------------------------------------------------------------*/
334    for (i = 0; i < n_sections; i++)
335    {
336        SCNHDR   *sptr = SECT_HDR(i);
337        O_SCNHDR *tptr = O_SECT_HDR(i);
339        if (byte_swapped)
340        {
341           /*-----------------------------------------------------------------*/
342           /* Swap sections according to native COFF version.                 */
343           /*-----------------------------------------------------------------*/
344           if (ISCOFF_2(coff_version))
345           {
346              if (sptr->s_zeroes == 0L) swap4byte(&sptr->s_offset);
347              swap4byte(&sptr->s_paddr);  
348              swap4byte(&sptr->s_vaddr);
349              swap4byte(&sptr->s_size);   
350              swap4byte(&sptr->s_scnptr);
351              swap4byte(&sptr->s_relptr); 
352              swap4byte(&sptr->s_lnnoptr);
353              swap4byte(&sptr->s_nreloc); 
354              swap4byte(&sptr->s_nlnno);
355              swap4byte(&sptr->s_flags);  
356              /* s_mwidth   - single byte */
357              /* s_reserved - single byte */
358              swap2byte(&sptr->s_page);
359           }
360           else
361           {
362              swap4byte(&tptr->os_paddr);  
363              swap4byte(&tptr->os_vaddr);
364              swap4byte(&tptr->os_size);   
365              swap4byte(&tptr->os_scnptr);
366              swap4byte(&tptr->os_relptr); 
367              swap4byte(&tptr->os_lnnoptr);
368              swap2byte(&tptr->os_nreloc); 
369              swap2byte(&tptr->os_nlnno);
370              swap2byte(&tptr->os_flags);
371              /* os_reserved - one byte */
372              /* os_page     - one byte */
373           }
374        }
376        /*---------------------------------------------------------------------*/
377        /* Old COFF version section headers are now ready to be transferred.   */
378        /*---------------------------------------------------------------------*/
379        if (!ISCOFF_2(coff_version))
380        {
381           strn_copy(sptr->s_name, tptr->os_name, SYMNMLEN);
382           sptr->s_paddr   = tptr->os_paddr;
383           sptr->s_vaddr   = tptr->os_vaddr;
384           sptr->s_size    = tptr->os_size;
385           sptr->s_scnptr  = tptr->os_scnptr;
386           sptr->s_relptr  = tptr->os_relptr;
387           sptr->s_lnnoptr = tptr->os_lnnoptr;
388           sptr->s_nreloc  = tptr->os_nreloc;
389           sptr->s_nlnno   = tptr->os_nlnno;
390           sptr->s_flags   = tptr->os_flags;
391           sptr->s_page    = tptr->os_page;
392        }
394        reloc_amount[i] = 0;
396 #if 0    // not to search the string table
397       /*---------------------------------------------------------------------*/
398       /* Fix up section name if it is a pointer into the string table.       */
399       /*---------------------------------------------------------------------*/
400       if (sptr->s_zeroes == 0L)
401       {
402          STRTAB *packet = str_head;
404          if (packet == NULL) 
405          {
406              return -1;
407          }
409          if (str_head->offset > sptr->s_offset)
410          {
411              return -1;
412          }
414          while (sptr->s_offset < (int)packet->offset) packet = packet->next;
415          sptr->s_nptr = packet->buf + (sptr->s_offset - packet->offset);
416       }
417 #endif
418    } // for ends
421    /*-------------------------------------------------------------------------*/
422    /* CALL AN EXTERNAL ROUTINE TO DETERMINE THE RELOCATION AMOUNTS FOR        */
423    /* EACH SECTION.                                                           */
424    /*-------------------------------------------------------------------------*/
425    if (!set_reloc_amount()) { load_err = E_SETRELOC; return FALSE; }
426    for (i = 0; i < n_sections; i++) need_reloc |= (reloc_amount[i] != 0);
427    if (!need_data) need_reloc = FALSE;
429    if (need_reloc && (file_hdr.f_flags & F_RELFLG)) 
430       { load_err = E_RELOC; return FALSE; }
432    return TRUE;
435 \f
436 /******************************************************************************/
437 /*                                                                            */
438 /* CLOAD_DATA() - Read in the raw data and load it into memory.               */
439 /*                                                                            */
440 /******************************************************************************/
441 int cload_data()
443    int ok = TRUE;
445    if (!need_data) return TRUE;
447    /*-------------------------------------------------------------------------*/
448    /* LOOP THROUGH THE SECTIONS AND LOAD THEM ONE AT A TIME.                  */
449    /*-------------------------------------------------------------------------*/
450    for (curr_sect = 0; curr_sect < n_sections && ok; curr_sect++)
451    {
452       SCNHDR *sptr = SECT_HDR(curr_sect);                        
453       char   *sname = (sptr->s_zeroes == 0L) ? 
454                                 sptr->s_nptr : SNAMECPY(sptr->s_name);
456       /*----------------------------------------------------------------------*/
457       /* IF THIS IS THE TEXT SECTION, RELOCATE THE ENTRY POINT.               */
458       /*----------------------------------------------------------------------*/
459       if ((sptr->s_flags & STYP_TEXT) && !str_comp(sname, ".text"))
460          entry_point += RUN_RELOC_AMOUNT(curr_sect);
462       /*----------------------------------------------------------------------*/
463       /* IGNORE EMPTY SECTIONS OR SECTIONS WHOSE FLAGS INDICATE THE           */
464       /* SECTION IS NOT TO BE LOADED.  IF THE CLEAR_BSS FLAG IS SET, BSS      */
465       /* IS "LOADED" EVEN THOUGH IT HAS NO DATA, AND DEFER THE CINIT          */
466       /* SECTION UNTIL LATER TO ENSURE BSS IS LOADED FIRST.                   */
467       /*----------------------------------------------------------------------*/
468       if ((sptr->s_scnptr || ((clear_bss || fill_bss) && IS_BSS(sptr)))   &&
469           (sptr->s_size)                                              &&
470           !(sptr->s_flags & (STYP_DSECT | STYP_COPY | STYP_NOLOAD)))
471           ok &= cload_sect_data(sptr);
472    }
474   /*-------------------------------------------------------------------------*/
475   /* WE DEFERRED CINIT, LOAD IT/THEM NOW.                                    */
476   /*-------------------------------------------------------------------------*/
477   for (curr_sect = 0; curr_sect < n_sections && ok; curr_sect++)
478   {
479      SCNHDR *sptr = SECT_HDR(curr_sect);
480      char   *sname = (sptr->s_zeroes == 0L) ? 
481                                sptr->s_nptr : SNAMECPY(sptr->s_name);
482      
483      if (IS_CINIT(sptr))
484      {
485                 ok &= cload_sect_data(sptr);
486      }
487   }
489    return ok;
492 \f
493 /******************************************************************************/
494 /*                                                                            */
495 /* CLOAD_SECT_DATA() - Read, relocate, and write out the data for one section.*/
496 /*                                                                            */
497 /******************************************************************************/
498 int cload_sect_data(SCNHDR *sptr)
500    T_ADDR        addr    = sptr->s_vaddr; /* CURRENT ADDRESS IN SECTION       */
501    unsigned int nbytes;                  /* BYTE COUNT WITHIN SECTION        */
502    int           packet_size = 0;         /* SIZE OF CURRENT DATA BUFFER      */
503    int           excess  = 0;             /* BYTES LEFT FROM PREVIOUS BUFFER  */
504    unsigned int  n_reloc = 0;             /* COUNTER FOR RELOCATION ENTRIES   */
505    RELOC         reloc;                   /* RELOCATION ENTRY                 */
506    int           relsz   = RELSZ_IN(coff_version); 
507    unsigned char *packet = NULL;          /* LOAD BUFFER                      */
508    unsigned int section_length = (unsigned int)LOCTOBYTE(sptr->s_size);
509    unsigned int buffer_size    = LOADBUFSIZE;
511 #if defined (UNBUFFERED) && UNBUFFERED
512    /*-------------------------------------------------------------------------*/
513    /* IF UNBUFFERED, THEN SET SIZE TO SECTION LENGTH ROUNDED UP TO MULTIPLE   */
514    /* 32 BYTES.  WE MAINTAIN A MINIMIUM OF LOADBUFSIZE IN THE EVENT SOMEONE   */
515    /* CONTINUES TO USE THAT MACRO AS A SIZE LIMIT.                            */
516    /*-------------------------------------------------------------------------*/
517    buffer_size = MAX(buffer_size, (section_length + 32) & ~31ul); 
518 #endif
520    /*-------------------------------------------------------------------------*/
521    /* ENSURE LOADBUFSIZE IS A MULTIPLE OF 2                                   */
522    /*-------------------------------------------------------------------------*/
523    if (LOADBUFSIZE % 2) 
524    {
525        return -1;
526    }
528    /*-------------------------------------------------------------------------*/
529    /* READ THE FIRST RELOCATION ENTRY, IF THERE ARE ANY.                      */
530    /* IF THIS IS A BSS SECTION, CLEAR THE LOAD BUFFER.                        */
531    /*-------------------------------------------------------------------------*/
532 #if FILE_BASED   
533    if (need_reloc && sptr->s_nreloc &&
534        (fseek(fin, sptr->s_relptr, 0) != 0 || !reloc_read(&reloc)))
535       { load_err = E_FILE; return FALSE; }
536 #else
537         // need_reloc is not used....
538         if (need_reloc && sptr->s_nreloc && !reloc_read(&reloc, sptr->s_relptr))
539       { load_err = E_FILE; return FALSE; }
540 #endif
541    /*-------------------------------------------------------------------------*/
542    /* ALLOCATE THE PACKET BUFFER                                              */
543    /*-------------------------------------------------------------------------*/
544    packet = (unsigned char *) malloc(buffer_size);
545    if (!packet) { load_err = E_ALLOC; return FALSE; }
547 #ifdef OTIS
548    if (IS_BSS(sptr))
549    {
550       TRG_MVAL filval = fill_bss_value;
552       free (packet);
554       if (!mem_fill(filval, LOCTOBYTE(sptr->s_size), addr, sptr->s_page))
555          { load_err = E_MEMWRITE; return FALSE; }
556       return TRUE;
557    }
558 #else
559    /*-------------------------------------------------------------------------*/
560    /* Always want to clear memory for cases where memsize is not a multiple   */
561    /* of the data size being written out.  If we do not clear the array, the  */
562    /* last byte or so can be corrupted with data from the last buffer read.   */
563    /*-------------------------------------------------------------------------*/
564    for (nbytes = 0; nbytes < buffer_size; ++nbytes) packet[nbytes] = 0;
565 #endif
566        
567    /*-------------------------------------------------------------------------*/
568    /* COPY ALL THE DATA IN THE SECTION.                                       */
569    /*-------------------------------------------------------------------------*/
571    for (nbytes = 0; nbytes < section_length; nbytes += packet_size)
572    {
573       int j;
575       /*----------------------------------------------------------------------*/
576       /* READ IN A BUFFER OF DATA.  IF THE PREVIOUS RELOCATION SPANNED        */
577       /* ACROSS THE END OF THE LAST BUFFER, COPY THE LEFTOVER BYTES INTO      */
578       /* THE BEGINNING OF THE NEW BUFFER.                                     */
579       /*----------------------------------------------------------------------*/
580       for (j = 0; j < excess; ++j) packet[j] = packet[packet_size + j];
582       packet_size = (int)MIN(LOCTOBYTE(sptr->s_size) - nbytes, buffer_size);
584       if (sptr->s_scnptr)
585 #if FILE_BASED   
586           if ((fseek(fin, sptr->s_scnptr + (int)(nbytes + excess), 0) != 0) ||
587               (fread(packet + excess, packet_size - excess, 1, fin) != 1))
588            { 
589               load_err = E_FILE; 
590               free (packet);
591               return FALSE; 
592           }
593 #else
594         mem_copy((void*)(packet + excess), (void*)&gRxBuffer[sptr->s_scnptr + (int)(nbytes + excess)], packet_size - excess);
595 #endif
598       excess = 0;
600       /*----------------------------------------------------------------------*/
601       /* Clear out end of packet in case we write padding.                    */
602       /*----------------------------------------------------------------------*/
603       if (excess + packet_size < buffer_size)
604           for(j = excess + packet_size; j < buffer_size; j++)
605               packet[j] = 0;
607       /*----------------------------------------------------------------------*/
608       /* READ AND PROCESS ALL THE RELOCATION ENTRIES THAT AFFECT DATA         */
609       /* CURRENTLY IN THE BUFFER.                                             */
610       /*----------------------------------------------------------------------*/
611       if (need_reloc)
612          while (n_reloc < sptr->s_nreloc && 
613                 (T_ADDR)reloc.r_vaddr < addr + BYTETOLOC(packet_size))
614          {
615             int i       = (int)LOCTOBYTE(reloc.r_vaddr - addr);   /* BYTE NDX */
616             int fieldsz = reloc_size(reloc.r_type);               /* IN BITS  */
617             int wordsz  = MAX(fieldsz, reloc_stop(reloc.r_type)); /* IN BITS  */
619             /*----------------------------------------------------------------*/
620             /* IF THIS RELOCATION SPANS PAST THE END OF THE BUFFER,           */
621             /* SET 'EXCESS' TO THE NUMBER OF REMAINING BYTES AND FLUSH THE    */
622             /* BUFFER.  AT THE NEXT FILL, THESE BYTES WILL BE COPIED FROM     */
623             /* THE END OF THE BUFFER TO THE BEGINNING AND THEN RELOCATED.     */
624             /*----------------------------------------------------------------*/
625             if (i + (wordsz >> 3) > packet_size)
626             { 
627                i          -= i % LOADWORDSIZE;   /* DON'T BREAK WITHIN A WORD */
628                excess      = packet_size - i; 
629                packet_size = i;
630                break;
631             }
633             /*----------------------------------------------------------------*/
634             /* PERFORM THE RELOCATION AND READ IN THE NEXT RELOCATION ENTRY.  */
635             /*----------------------------------------------------------------*/
636 #if 0
637             if (!relocate(&reloc, packet + i, curr_sect)) 
638                 { free (packet); return FALSE; }
639 #endif
641 #if FILE_BASED  
642             if (n_reloc++ < sptr->s_nreloc                                    &&
643                (fseek(fin, sptr->s_relptr + ((int)n_reloc * relsz), 0) != 0  ||
644                  !reloc_read(&reloc)))
645 #else
646                 if (n_reloc++ < sptr->s_nreloc && !reloc_read(&reloc, sptr->s_relptr + ((int)n_reloc * relsz)));
647 #endif           
648                { load_err = E_FILE; free (packet); return FALSE; }
649          }
651       /*----------------------------------------------------------------------*/
652       /* WRITE OUT THE RELOCATED DATA TO THE TARGET DEVICE.  IF THIS IS A     */
653       /* CINIT SECTION, CALL A SPECIAL FUNCTION TO HANDLE IT.                 */
654       /*----------------------------------------------------------------------*/
655       if (!(IS_CINIT(sptr) ?
656               cload_cinit(packet, &packet_size, &excess) :
657               (int) mem_write(packet, packet_size, addr + reloc_amount[curr_sect], 
658                                                             sptr->s_page)))
659          { load_err = E_MEMWRITE; free (packet); return FALSE; }
661       /*----------------------------------------------------------------------*/
662       /* KEEP TRACK OF THE ADDRESS WITHIN THE SECTION.                        */
663       /*----------------------------------------------------------------------*/
664       addr += BYTETOLOC(packet_size);
666    }
668    free (packet);
669    return TRUE;
672 \f
673 /******************************************************************************/
674 /*                                                                            */
675 /* CLOAD_CINIT() - Process one buffer of C initialization records.            */
676 /*                                                                            */
677 /******************************************************************************/
678 int cload_cinit(unsigned char *packet, int *packet_size, int *excess)
680    int           i;                      /* BYTE COUNTER                      */
681    int           init_packet_size;       /* SIZE OF CURRENT INITIALIZATION    */
682    static T_ADDR init_addr;              /* ADDRESS OF CURRENT INITIALIZATION */
683    int           bss_page = 0;           /* BSS SECTION PAGE NUMBER           */
684  
685    /*-------------------------------------------------------------------------*/
686    /* FIND THE BSS SECTION ASSOCIATED WITH THE THE CINIT SECTION CURRENTLY    */
687    /* BEING LOADED.                                                           */
688    /*-------------------------------------------------------------------------*/
689    for (i = 0; i < n_sections; ++i)
690       if (IS_BSS(SECT_HDR(i))) 
691           { bss_page = SECT_HDR(i)->s_page; break; }
693    /*-------------------------------------------------------------------------*/
694    /*  PROCESS ALL THE INITIALIZATION RECORDS IN THE BUFFER.                  */
695    /*-------------------------------------------------------------------------*/
696    for (i = 0; i < *packet_size; i += init_packet_size)
697    {
698       /*----------------------------------------------------------------------*/
699       /* IF STARTING A NEW INITIALIZATION, READ THE SIZE AND ADDRESS FROM     */
700       /* THE TABLE.                                                           */
701       /*----------------------------------------------------------------------*/
702       if (init_size == 0)
703       {
704          T_SIZE temp;
705          int    align;
707          /*-------------------------------------------------------------------*/
708          /* POSITION THE BYTE INDEX ON THE NEXT INIT RECORD.                  */
709          /*-------------------------------------------------------------------*/
710          if (align = (i % INIT_ALIGN)) i += (INIT_ALIGN - align);
712          /*-------------------------------------------------------------------*/
713          /* IF THE SIZE AND ADDRESS ARE NOT FULLY CONTAINED IN THIS BUFFER,   */
714          /* STOP HERE.  SET THE 'EXCESS' COUNTER TO THE NUMBER OF UNPROCESSED */
715          /* BYTES - THESE WILL BE COPIED TO THE HEAD OF THE NEXT BUFFER.      */
716          /*-------------------------------------------------------------------*/
717          if ((int)(i + sizeof(T_SIZE)) > *packet_size)
718             { *excess += *packet_size - i;  *packet_size = i;  break; }
720          /*-------------------------------------------------------------------*/
721          /* IF THE NEXT SIZE FIELD IS ZERO, BREAK.                            */
722          /*-------------------------------------------------------------------*/
723          temp = unpack(packet + i, sizeof(T_SIZE)*8, sizeof(T_SIZE)*8, 0);
724          if (temp == 0) break;
726          /*-------------------------------------------------------------------*/
727          /* READ THE ADDRESS FIELD ,IF IT'S ALL HERE.                         */
728          /*-------------------------------------------------------------------*/
729          if ((int)(i + sizeof(T_SIZE) + sizeof(T_IADDR)) > *packet_size)
730              { *excess += *packet_size - i;  *packet_size = i;  break; }
732          i         += sizeof(T_SIZE);
733          init_size  = temp;
734          init_addr  = unpack(packet+i,sizeof(T_IADDR)*8,sizeof(T_IADDR)*8,0);
735          i         += sizeof(T_IADDR);
736       }
738       /*----------------------------------------------------------------------*/
739       /* WRITE OUT THE CURRENT PACKET, UP TO THE END OF THE BUFFER.           */
740       /*----------------------------------------------------------------------*/
741       if (init_packet_size = MIN(*packet_size-i, (int)(init_size * INIT_WSIZE)))
742       {
743         
744          if (!mem_write(packet + i, init_packet_size, init_addr, bss_page))
745             return FALSE;
747          init_addr += BYTETOLOC(init_packet_size);
748          init_size -= init_packet_size / INIT_WSIZE;
749       }
750    }
751    return TRUE;
754 #if 0
755 /******************************************************************************/
756 /*                                                                            */
757 /* CLOAD_SYMBOLS() - Read in the symbol table.                                */
758 /*                                                                            */
759 /******************************************************************************/
760 int cload_symbols()
762    SYMENT sym;
763    AUXENT aux;
764    int first, next;
766    if (file_hdr.f_nsyms == 0 || (!need_symbols && !need_reloc)) return TRUE;
768    /*------------------------------------------------------------------------*/
769    /* ALLOCATE THE RELOCATION SYMBOL TABLE.                                  */
770    /*------------------------------------------------------------------------*/
771    if (need_reloc)
772    {
773       reloc_sym_index = 0;
774       reloc_tab_size  = MIN(RELOC_TAB_START, (int)file_hdr.f_nsyms);
776       if (!(reloc_tab = (RELOC_TAB *)malloc(reloc_tab_size*sizeof(RELOC_TAB))))
777           { load_err = E_ALLOC; return FALSE; }
778    }
780    /*------------------------------------------------------------------------*/
781    /* IF THE APPLICATION NEEDS THE SYMBOL TABLE, LET IT READ IT IN.          */
782    /* PASS NEED_RELOC TO THE APPLICATION SO THAT IT CAN CALL RELOC_ADD().    */
783    /*------------------------------------------------------------------------*/
784    if (need_symbols) 
785    {
786       if (load_syms(need_reloc)) return TRUE;
787       else { load_err = E_SYM; return FALSE; }
788    }
790    /*------------------------------------------------------------------------*/
791    /*  READ THE SYMBOL TABLE AND BUILD THE RELOCATION SYMBOL TABLE           */
792    /*  FOR SYMBOLS THAT CAN BE USED IN RELCOATION, STORE THEM IN A           */
793    /*  SPECIAL SYMBOL TABLE THAT CAN BE SEARCHED QUICKLY DURING              */
794    /*  RELOCATION.                                                           */
795    /*------------------------------------------------------------------------*/
796    for (first = 0; first < file_hdr.f_nsyms; first = next)
797    {
798        if (!(next = sym_read(first, &sym, &aux))) 
799           { load_err = E_FILE; return FALSE; }
801        if (sym.n_sclass == C_EXT     || sym.n_sclass == C_EXTREF  ||
802            sym.n_sclass == C_STAT    || sym.n_sclass == C_LABEL   ||
803            sym.n_sclass == C_SYSTEM  || sym.n_sclass == C_BLOCK   || 
804            sym.n_sclass == C_FCN     || sym.n_sclass == C_STATLAB || 
805            sym.n_sclass == C_EXTLAB) 
806           if (!reloc_add(first, &sym)) return FALSE;
807    }
808    return TRUE;
812 /******************************************************************************/
813 /*                                                                            */
814 /* CLOAD_STRINGS() - Read in the string table.                                */
815 /*                                                                            */
816 /******************************************************************************/
817 int cload_strings()
819    unsigned int str_size;              /* SIZE OF STRING TABLE              */
820    unsigned int bufsize;               /* SIZE OF CURRENT BUFFER            */
821    unsigned int ntoread;                /* AMOUNT TO READ FROM FILE          */
822    int excess;                          /* AMOUNT LEFT OVER FROM LAST BUFFER */
823    STRTAB *packet;                      /* STRING TABLE BUFFER PACKET        */
824    unsigned int i = 0;
826    /*----------------------------------------------------------------------*/
827    /* Do not load if not loading/saving the symbol tables.                 */
828    /* This is because the string table is an extension of the symbol table */
829    /* and if you free and rebuild it, the symbol table's str_head will be  */
830    /* incorrect.                                                           */
831    /*----------------------------------------------------------------------*/
832    if (!need_symbols) return TRUE;
834    /*------------------------------------------------------------------------*/
835    /* FREE ANY PREVIOUS STRING BUFFERS                                       */
836    /*------------------------------------------------------------------------*/
837    str_free(str_head); str_head = NULL;
839    /*------------------------------------------------------------------------*/
840    /* SEEK TO THE END OF THE SYMBOL TABLE AND READ IN THE SIZE OF THE STRING */
841    /* TABLE.                                                                 */
842    /*------------------------------------------------------------------------*/
843 #if FILE_BASED
844    if ((file_hdr.f_nsyms == 0) ||
845            fseek(fin, file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ), 0) != 0 ||
846        fread(&str_size, sizeof(int), 1, fin) != 1)
847        return TRUE;
848 #else
849    mem_copy(&str_size, &gRxBuffer[file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ)], sizeof(int));       
850    if ((file_hdr.f_nsyms == 0))
851        return TRUE; 
852 #endif
853    if (byte_swapped) swap4byte(&str_size);
855    /*------------------------------------------------------------------------*/
856    /* THE STRING TABLE IS READ IN AS A LINKED LIST OF BUFFERS.  TO           */
857    /* PREVENT NAMES FROM BEING SPLIT ACROSS MULTIPLE BUFFERS, ANY PARTIAL    */
858    /* NAME AT THE END OF A BUFFER IS COPIED INTO THE BEGINNING OF THE        */
859    /* NEXT BUFFER.  THE VARIABLE 'EXCESS' KEEPS TRACK OF HOW MUCH NEEDS      */
860    /* TO BE COPIED FROM THE PREVIOUS BUFFER.                                 */
861    /*------------------------------------------------------------------------*/
862    str_size -= 4;                       /* SUBTRACT OFF 4 BYTES ALREADY READ */
863    excess    = 0;                       /* INITIALIZE LAST-BUFFER OVERFLOW   */
866    /*------------------------------------------------------------------------*/
867    /* READ STRING BUFFERS UNTIL THE WHOLE STRING TABLE IS READ.              */
868    /*------------------------------------------------------------------------*/
869    while (str_size)
870    {
871       /*---------------------------------------------------------------------*/
872       /* ALLOCATE A NEW BUFFER.  ON 16-BIT MACHINES, RESTRICT THE            */
873       /* BUFFER SIZE TO THE MAXIMUM THAT CAN BE ALLOCATED AT ONCE.           */
874       /*---------------------------------------------------------------------*/
875       bufsize = str_size + excess;
877       if (sizeof(int) < 4  && bufsize > MAX_STRING_ALLOC)
878          bufsize = MAX_STRING_ALLOC;
880       if (!(packet = (struct strtab *)malloc(sizeof(STRTAB) + 
881                                              (unsigned int)bufsize - 1)))
882          { load_err = E_ALLOC; return FALSE; }
884       /*---------------------------------------------------------------------*/
885       /* COPY ANY PARTIAL STRING FROM THE LAST BUFFER INTO THIS ONE.         */
886       /* THEN FILL THE REST OF THE BUFFER BY READING FROM THE FILE.          */
887       /*---------------------------------------------------------------------*/
888       if (excess)
889          strn_copy(packet->buf, str_head->buf + str_head->size, excess);
891       ntoread = (unsigned int)(bufsize - excess);
892 #if FILE_BASED
893       if (fread(packet->buf + excess, ntoread, 1, fin) != 1) 
894          { load_err = E_FILE; return FALSE; }
895 #else
896         mem_copy(packet->buf + excess, &gRxBuffer[file_hdr.f_symptr + (file_hdr.f_nsyms * SYMESZ) +sizeof(int)+ i++*ntoread], ntoread);
897 #endif   
898       str_size -= ntoread;
900       /*---------------------------------------------------------------------*/
901       /* IF THE BUFFER ENDS IN A PARTIAL STRING (DOESN'T END IN NULL),       */
902       /* KEEP TRACK OF HOW MANY CHARACTERS ARE IN THE PARTIAL STRING         */
903       /* SO THEY CAN BE COPIED INTO THE NEXT BUFFER.                         */
904       /*---------------------------------------------------------------------*/
905       for (excess = 0; packet->buf[bufsize - 1]; --bufsize, ++excess) ;
907       /*---------------------------------------------------------------------*/
908       /* LINK THE NEW BUFFER INTO THE HEAD OF THE LIST.                      */
909       /*---------------------------------------------------------------------*/
910       packet->size   = 
911       packet->index  = bufsize;
912       packet->next   = str_head;
913       packet->offset = str_head ? (str_head->offset + str_head->size) : 4;
914       str_head       = packet;
915    }
916    return TRUE;
919 \f
920 /******************************************************************************/
921 /*                                                                            */
922 /* STR_FREE() - Free the list of string table buffers.                        */
923 /*                                                                            */
924 /******************************************************************************/
925 void str_free(STRTAB *head)
927    STRTAB *this_one, *next;
928    for (this_one = head; this_one; this_one = next)
929    {
930       next = this_one->next;
931       free(this_one);
932    }
937 /******************************************************************************/
938 /*                                                                            */
939 /* SYM_READ() - Read and relocate a symbol and its aux entry.  Return the     */
940 /*              index of the next symbol.                                     */
941 /*                                                                            */
942 /******************************************************************************/
943 int sym_read(int index, SYMENT *sym, AUXENT *aux)
945     /*------------------------------------------------------------------------*/
946     /* READ IN A SYMBOL AND ITS AUX ENTRY.                                    */
947     /*------------------------------------------------------------------------*/
948 #if FILE_BASED
949     if (fseek(fin, file_hdr.f_symptr + (index * SYMESZ), 0) != 0 ||
950         fread(sym, SYMESZ, 1, fin) != 1                                ||
951         (sym->n_numaux && fread(aux, SYMESZ, 1, fin) != 1)) 
952       { load_err = E_FILE; return FALSE; }
953 #else
954         mem_copy((void*)sym, (void*)&gRxBuffer[file_hdr.f_symptr + (index * SYMESZ)], SYMESZ); 
955     if (sym->n_numaux) 
956     { 
957         mem_copy((void*)aux, (void*)&gRxBuffer[file_hdr.f_symptr + ( (index+1) * SYMESZ)], SYMESZ);
958         load_err = E_FILE; 
959         return FALSE; 
960     }
961 #endif
962     if (byte_swapped)
963     {
964         /*--------------------------------------------------------------------*/
965         /* SWAP THE SYMBOL TABLE ENTRY.                                       */
966         /*--------------------------------------------------------------------*/
967         if (sym->n_zeroes == 0) swap4byte(&sym->n_offset);
968         swap4byte(&sym->n_value);
969         swap2byte(&sym->n_scnum);
970         swap2byte(&sym->n_type);
972         /*--------------------------------------------------------------------*/
973         /* SWAP THE AUX ENTRY, BASED ON THE STORAGE CLASS.                    */
974         /*--------------------------------------------------------------------*/
975         if (sym->n_numaux) switch(sym->n_sclass)
976         {
977           case C_FILE    : break;
979           case C_STRTAG  :
980           case C_UNTAG   :
981           case C_ENTAG   : swap4byte(&aux->x_tag.x_fsize);
982                            swap4byte(&aux->x_tag.x_endndx);
983                            break;
985           case C_FCN     : if (!str_comp(sym->n_name, ".bf"))
986                            {
987                                swap2byte(&aux->x_block.x_lcnt);
988                                swap4byte(&aux->x_block.x_regmask); 
989                                swap4byte(&aux->x_block.x_framesize);
990                            }
991                                 
992           case C_BLOCK   : swap2byte(&aux->x_block.x_lnno);
993                            swap4byte(&aux->x_block.x_endndx);
994                            break;
996           case C_EOS     : swap4byte(&aux->x_eos.x_fsize);
997                            swap4byte(&aux->x_eos.x_tagndx);
998                            break;
1000           default        : /*-------------------------------------------------*/
1001                            /* HANDLE FUNCTION DEFINITION SYMBOL               */
1002                            /*-------------------------------------------------*/
1003                            if (((sym->n_type >> 4) & 3) == DCT_FCN)
1004                            {
1005                                swap4byte(&aux->x_func.x_tagndx);
1006                                swap4byte(&aux->x_func.x_fsize);
1007                                swap4byte(&aux->x_func.x_lnnoptr);
1008                                swap4byte(&aux->x_func.x_endndx);
1009                            }
1011                            /*-------------------------------------------------*/
1012                            /* HANDLE ARRAYS.                                  */
1013                            /*-------------------------------------------------*/
1014                            else if (((sym->n_type >> 4) & 3) == DCT_ARY)
1015                            {
1016                                swap4byte(&aux->x_array.x_tagndx);
1017                                swap4byte(&aux->x_array.x_fsize);
1018                                swap2byte(&aux->x_array.x_dimen[0]);
1019                                swap2byte(&aux->x_array.x_dimen[1]);
1020                                swap2byte(&aux->x_array.x_dimen[2]);
1021                                swap2byte(&aux->x_array.x_dimen[3]);
1022                            }
1024                            /*-------------------------------------------------*/
1025                            /* HANDLE SECTION DEFINITIONS                      */
1026                            /*-------------------------------------------------*/
1027                            else if (sym->n_type == 0)
1028                            {
1029                                swap4byte(&aux->x_scn.x_scnlen);
1030                                swap2byte(&aux->x_scn.x_nreloc);
1031                                swap2byte(&aux->x_scn.x_nlinno);
1032                            }
1034                            /*-------------------------------------------------*/
1035                            /* HANDLE MISC SYMBOL RECORD                       */
1036                            /*-------------------------------------------------*/
1037                            else
1038                            {
1039                                swap4byte(&aux->x_sym.x_fsize);
1040                                swap4byte(&aux->x_sym.x_tagndx);
1041                            }
1042         }
1043     }
1045     /*------------------------------------------------------------------------*/
1046     /* RELOCATE THE SYMBOL, BASED ON ITS STORAGE CLASS.                       */
1047     /*------------------------------------------------------------------------*/
1048     switch(sym->n_sclass)
1049     {
1050        case C_SYSTEM  :
1051        case C_EXT     :
1052        case C_EXTREF  :
1053        case C_STAT    :
1054        case C_LABEL   :
1055        case C_BLOCK   :
1056        case C_FCN     : 
1057        case C_STATLAB :
1058        case C_EXTLAB  :
1059           /*------------------------------------------------------------------*/
1060           /* IF THE SYMBOL IS UNDEFINED, CALL AN APPLICATION ROUTINE TO LOOK  */
1061           /* IT UP IN AN EXTERNAL SYMBOL TABLE.  IF THE SYMBOL IS DEFINED,    */
1062           /* RELOCATE IT ACCORDING TO THE SECTION IT IS DEFINED IN.           */
1063           /*------------------------------------------------------------------*/
1064           if (sym->n_scnum == 0) 
1065              lookup_sym((short)index, sym, aux);
1066           else if (sym->n_scnum > 0) 
1067           {
1068              if (sym->n_sclass == C_STATLAB || sym->n_sclass == C_EXTLAB)
1069                   sym->n_value += reloc_amount[sym->n_scnum - 1];
1070              else sym->n_value += RUN_RELOC_AMOUNT(sym->n_scnum - 1);
1071           }
1072     }
1074     return (index + sym->n_numaux + 1);
1077 \f
1078 /******************************************************************************/
1079 /*                                                                            */
1080 /* SYM_NAME() - Return a pointer to the name of a symbol in either the symbol */
1081 /*              entry or the string table.                                    */
1082 /*                                                                            */
1083 /******************************************************************************/
1084 char *sym_name(SYMENT *symptr)
1086     static char temp[9];
1088     if (symptr->n_zeroes == 0)
1089     {
1090        STRTAB *packet = str_head;
1092        /*---------------------------------------------------------------------*/
1093        /* Return the empty string if this symbol has no name (offset == 0)    */
1094        /*---------------------------------------------------------------------*/
1095        if (symptr->n_offset < 4) /* Anything below 4 isn't valid */
1096        {
1097           temp[0] = 0;
1098           return temp;
1099        }
1101        /*---------------------------------------------------------------------*/
1102        /* Otherwise, return the string in the string table.                   */
1103        /*---------------------------------------------------------------------*/
1104        while (packet && symptr->n_offset < (int)packet->offset)
1105           packet = packet->next;
1107        /*---------------------------------------------------------------------*/
1108        /* Return the empty string if packet NULL (invalid offset)             */
1109        /*---------------------------------------------------------------------*/
1110        if (!packet)
1111        {
1112           temp[0] = 0;
1113           return temp;
1114        }
1116        return packet->buf + (symptr->n_offset - packet->offset);
1117     }
1118     
1119     strn_copy(temp, symptr->n_name, 8);
1120     temp[8] = 0;
1121     return temp;
1125 /******************************************************************************/
1126 /*                                                                            */
1127 /* SYM_ADD_NAME() - Given a symbol table entry, return a pointer to the       */
1128 /*                  symbol's name in the string table.  Add the name to the   */
1129 /*                  table if it's not already there.                          */
1130 /*                                                                            */
1131 /******************************************************************************/
1132 char *sym_add_name(SYMENT *symptr)
1134     char *dest;
1135     char *result;
1136     int i;
1138     /*------------------------------------------------------------------------*/
1139     /* IF THE SYMBOL'S NAME WAS IN THE COFF STRING TABLE, LOOK THROUGH THE    */
1140     /* LIST OF STRING TABLE BUFFERS UNTIL FINDING THE ONE THE NAME IS IN,     */
1141     /* AND SIMPLY POINT INTO THE BUFFER.                                      */
1142     /*------------------------------------------------------------------------*/
1143     if (symptr->n_zeroes == 0)
1144        return sym_name(symptr);
1146     /*------------------------------------------------------------------------*/
1147     /* OTHERWISE ADD THE STRING TO THE STRING TABLE.                          */
1148     /* ALLOCATE AND LINK IN A NEW PACKET IF NECESSARY.  NEW PACKETS ARE       */
1149     /* LINKED TO THE HEAD OF THE LIST TO EASE ADDING NEW SYMBOLS.             */
1150     /*------------------------------------------------------------------------*/
1151     if (!str_head || str_head->index + SYMNMLEN + 1 > str_head->size)
1152     {
1153        STRTAB *packet;
1155        if (!(packet = (STRTAB *)malloc(sizeof(STRTAB) + MIN_STRING_ALLOC - 1)))
1156           { load_err = E_ALLOC; return NULL; }
1158        packet->size   = MIN_STRING_ALLOC;
1159        packet->index  = 0;
1160        packet->next   = str_head;
1161        packet->offset = str_head ? (str_head->offset + str_head->size) : 4;
1162        str_head       = packet;
1163     }
1165     /*------------------------------------------------------------------------*/
1166     /* COPY THE NAME INTO THE STRING TABLE.                                   */
1167     /*------------------------------------------------------------------------*/
1168     result = dest = str_head->buf + str_head->index; 
1169     for (i = 0; *dest++ = symptr->n_name[i++]; )
1170        if (i == SYMNMLEN) { *dest++ = '\0'; ++i; break; }
1172     symptr->n_zeroes = 0;
1173     symptr->n_offset = str_head->offset + str_head->index;
1174     str_head->index += i;
1175     return result;
1177 #endif
1179 #if 0
1180 /******************************************************************************/
1181 /*                                                                            */
1182 /* RELOC_ADD() - Add an entry to the relocation symbol table.  This table     */
1183 /*               stores relocation information for each relocatable symbol.   */
1184 /*                                                                            */
1185 /******************************************************************************/
1186 int reloc_add(int index, SYMENT *sym)
1188    int disp;                            /* RELOCATION AMOUNT FOR THIS SYMBOL */
1190    if (!need_reloc) return TRUE;
1192    /*-------------------------------------------------------------------------*/
1193    /* USE THE SYMBOL VALUE TO CALCULATE THE RELOCATION AMOUNT:                */
1194    /* 1) IF THE SYMBOL WAS UNDEFINED (DEFINED IN SECTION 0), USE THE          */
1195    /*    SYMBOL'S VALUE.                                                      */
1196    /* 2) IF THE SYMBOL HAS A POSITIVE SECTION NUMBER, USE THE RELOCATION      */
1197    /*    AMOUNT FOR THE SECTION IN WHICH THE SYMBOL IS DEFINED.               */
1198    /* 3) OTHERWISE, THE SYMBOL IS ABSOLUTE, SO THE RELOCATION AMOUNT IS 0.    */
1199    /*-------------------------------------------------------------------------*/
1200    if (sym->n_scnum == 0)
1201       disp = sym->n_value;
1202    else if (sym->n_scnum > 0)
1203    {
1204       if (sym->n_sclass == C_STATLAB || sym->n_sclass == C_EXTLAB)
1205            disp = reloc_amount[sym->n_scnum - 1];
1206       else disp = RUN_RELOC_AMOUNT(sym->n_scnum - 1);
1207    }
1208    else disp = 0;
1210    /*-------------------------------------------------------------------------*/
1211    /* IF THERE IS A NON-ZERO RELOCATION AMOUNT, ADD THE SYMBOL TO THE TABLE.  */
1212    /*-------------------------------------------------------------------------*/
1213    if (disp == 0) return TRUE;
1215    if (reloc_sym_index >= reloc_tab_size)
1216    {
1217       reloc_tab_size += RELOC_GROW_SIZE;
1218       reloc_tab = (RELOC_TAB *)realloc((char *)reloc_tab, 
1219                                        reloc_tab_size*sizeof(RELOC_TAB));
1221       if (!reloc_tab) { load_err = E_ALLOC; return FALSE; }
1222    }
1223    reloc_tab[reloc_sym_index  ].rt_index = index;
1224    reloc_tab[reloc_sym_index++].rt_disp  = disp;
1226    return TRUE;
1231 /******************************************************************************/
1232 /*                                                                            */
1233 /* RELOCATE() - Perform a single relocation by patching the raw data.         */
1234 /*                                                                            */
1235 /******************************************************************************/
1236 int relocate(RELOC *rp, unsigned char *data, int s)
1238 /*   RELOC         *rp;                    RELOCATION ENTRY                   */
1239 /*   unsigned char *data;                  DATA BUFFER                        */
1240 /*   int            s;                     INDEX OF CURRENT SECTION           */
1241    int fieldsz = reloc_size(rp->r_type);     /* SIZE OF ACTUAL PATCH VALUE    */
1242    int offset  = reloc_offset(rp->r_type);   /* OFFSET OF ACTUAL PATCH VALUE  */
1243    int wordsz  = MAX(fieldsz, reloc_stop(rp->r_type)); /* SIZE CONTAINING FLD */
1244    int objval;                              /* FIELD TO BE PATCHED           */
1245    int reloc_amt;                           /* AMOUNT OF RELOCATION          */
1247    int pp_shift_cnt = 0;
1248    int pp_local     = FALSE;
1250    if (rp->r_type == R_ABS) return TRUE;          /* NOTHING TO DO   */
1252    /*-------------------------------------------------------------------------*/
1253    /* DETERMINE THE RELOCATION AMOUNT FROM THE RELOCATION SYMBOL TABLE.       */
1254    /*-------------------------------------------------------------------------*/
1255    reloc_amt = (rp->r_symndx == -1) ? RUN_RELOC_AMOUNT(s) 
1256                                     : sym_reloc_amount(rp);
1258    /*-------------------------------------------------------------------------*/
1259    /* EXTRACT THE RELOCATABLE FIELD FROM THE OBJECT DATA.                     */
1260    /*-------------------------------------------------------------------------*/
1261    objval = unpack(data, fieldsz, wordsz, offset + BIT_OFFSET(rp->r_vaddr));
1263    /*-------------------------------------------------------------------------*/
1264    /* MODIFY THE FIELD BASED ON THE RELOCATION TYPE.                          */
1265    /*-------------------------------------------------------------------------*/
1266    switch (rp->r_type)
1267    {
1268       /*----------------------------------------------------------------------*/
1269       /* NORMAL RELOCATIONS: ADD IN THE RELOCATION AMOUNT.                    */
1270       /*----------------------------------------------------------------------*/
1271       case R_RELBYTE:
1272       case R_RELWORD:
1273       case R_REL24:
1274       case R_RELLONG:
1275       case R_DIR32:
1276       case R_PARTLS16:
1277          objval += reloc_amt;
1278          break;
1280       /*--------------------------------------------------------------------*/
1281       /* ADD IN THE RELOCATION AMOUNT, BUT MAKE SURE WE'RE STILL IN THE     */
1282       /* 370'S REGISTER FILE.                                               */
1283       /*--------------------------------------------------------------------*/
1284       case R_RRNREG:
1285       case R_RRRELREG:
1286          if (rp->r_type == R_RRNREG)
1287             objval = ((char)objval + reloc_amt);
1288          else objval += reloc_amt;
1289  
1290          if (objval & ((-1L >> 8*fieldsz) << 8*fieldsz))
1291          {
1292             /* ERROR */
1293          }
1294  
1295          break;
1296  
1297       /*--------------------------------------------------------------------*/
1298       /* PP UNSCALED 15-BIT OFFSET RELOCATION.                              */
1299       /*--------------------------------------------------------------------*/
1300       case R_PP15    :
1301       case R_PPL15   :
1302       case R_PPN15   :
1303       case R_PPLN15  :
1304          {
1305             int  bit;
1306             char *sname = (SECT_HDR(s)->s_zeroes == 0L) ?
1307                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1309             pp_local = (rp->r_type == R_PPL15) || (rp->r_type == R_PPLN15);
1311             /*--------------------------------------------------------------*/
1312             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS A NEGATIVE*/
1313             /*--------------------------------------------------------------*/
1314             if (rp->r_type == R_PPN15 || rp->r_type == R_PPLN15)
1315             {
1316                 objval      = -objval;
1317                 rp->r_type -= 010;           /* CHANGE TYPE TO NON NEG.     */
1318             }
1320             objval += reloc_amt;
1322             /*--------------------------------------------------------------*/
1323             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1324             /*--------------------------------------------------------------*/
1325             if ((objval >= 0x00000000 && objval <= 0x00007fff) || 
1326                 (objval >= 0x01000000 && objval <= 0x010007ff) )
1327                 break;
1329             /*--------------------------------------------------------------*/
1330             /* IF THE ADDRESS FALLS OUTSIDE AN APPROPRIATE RANGE, BUT CAN   */
1331             /* BE SCALED BY SIZE TO GET BACK INTO RANGE, THEN READ THE UPPER*/
1332             /* BIT OF THE SIZE FIELD.  IF IT IS A 1, THEN WE CAN SCALE THIS */
1333             /* OFFSET BY 4, IF IT IS 0, THEN WE CAN SCALE THIS OFFSET BY 2. */ 
1334             /*--------------------------------------------------------------*/
1335             bit = unpack(data, 1, 64, pp_local ? 30 : 8);
1336  
1337             /*--------------------------------------------------------------*/
1338             /* DETERMINE IF THE OFFSET IS ALIGNED FOR SCALING.  IF SO,      */
1339             /* THEN PACK THE SCALED OFFSET INTO INSTRUCTION, CHANGE THE     */
1340             /* RELOC TYPE TO SCALED, AND TURN ON SCALE BIT IN INSTRUCT.     */
1341             /*--------------------------------------------------------------*/
1342             if (!(objval & ((2<<bit)-1)) && 
1343                  (objval >>= (bit+1)) >= 0 && objval <= 0x7fff)
1344             {
1345                 rp->r_type = pp_local ? (bit ? R_PPL15W : R_PPL15H) : 
1346                                         (bit ? R_PP15W : R_PP15H);
1347                 repack(1, data, 1, 64, pp_local ? 28 : 6);
1348                 break;
1349             }
1350             
1351             /*--------------------------------------------------------------*/
1352             /* ERROR, THE OFFSET WILL NOT FIT SCALED OR UNSCALED.           */
1353             /*--------------------------------------------------------------*/
1354             
1355             load_err = E_RELOCENT;
1356             return FALSE;
1357          }
1359       /*--------------------------------------------------------------------*/
1360       /* PP SCALED 15-BIT OFFSET RELOCATION. FOR R_PP15W THE RELOC_AMT IS   */
1361       /* DIVIDED BY 4.  FOR R_PP15H THE RELOC_AMT IS DIVIDED BY 2.          */ 
1362       /*--------------------------------------------------------------------*/
1363       case R_PP15W   :
1364       case R_PPL15W  :
1365       case R_PPN15W  :
1366       case R_PPLN15W :  pp_shift_cnt++;   /* FALL THROUGH */
1368       case R_PP15H   :
1369       case R_PPL15H  :
1370       case R_PPN15H  :
1371       case R_PPLN15H :  pp_shift_cnt++;   /* FALL THROUGH */
1372          {
1373             int obj_addr_x;
1374             char *sname = (SECT_HDR(s)->s_zeroes == 0) ? 
1375                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1377             /*--------------------------------------------------------------*/
1378             /* NOTE THAT THIS IS DEPENDENT ON THE NUMBERING OF THESE RELOC  */
1379             /* VALUES.                                                      */
1380             /*--------------------------------------------------------------*/
1381             pp_local = (rp->r_type & 4);
1383             /*--------------------------------------------------------------*/
1384             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS NEGATIVE  */
1385             /*--------------------------------------------------------------*/
1386             if (rp->r_type >= R_PPN15) 
1387             {
1388                 objval      = -objval;
1389                 rp->r_type -= 010;           /* CHANGE TYPE TO NON NEG.     */
1390             }
1392             obj_addr_x = (objval << pp_shift_cnt) + reloc_amt;
1394             /*--------------------------------------------------------------*/
1395             /* LINK TIME ADDRESS VIOLATES THE SCALING FACTOR WE ARE USING   */
1396             /* FOR THIS OPERAND. UNSCALE THE VALUE IF IT WILL FIT IN 15 BITS*/
1397             /* BY CHANGING RELOC TYPE TO UNSCALED, AND CHANGING SCALE BIT   */
1398             /* IN THE INSTRUCTION.                                          */
1399             /*--------------------------------------------------------------*/
1400             if (pp_shift_cnt && (reloc_amt & ((1<<pp_shift_cnt)-1)))
1401             {
1402                 objval     = obj_addr_x;
1403                 rp->r_type = (pp_local ? R_PPL15 : R_PP15);
1404                 repack(0, data, 1, 64, pp_local ? 28 : 6);
1405             }
1406             else objval = obj_addr_x >> pp_shift_cnt;
1408             /*--------------------------------------------------------------*/
1409             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1410             /*--------------------------------------------------------------*/
1411             if ((objval     >= 0x00000000  && objval     <= 0x00007fff) || 
1412                 (obj_addr_x >= 0x01000000  && obj_addr_x <= 0x010007ff) )
1413                 break;
1415             /*--------------------------------------------------------------*/
1416             /* ERROR, THE OFFSET WILL NOT FIT SCALED OR UNSCALED.           */
1417             /*--------------------------------------------------------------*/
1418             
1419             load_err = E_RELOCENT;
1420             return FALSE;
1421          }
1423       /*--------------------------------------------------------------------*/
1424       /* PP 16-bit byte offset relocation. For R_PP16B the lower 15-bits    */
1425       /* are handled just like R_PP15, and the upper bit is placed in the   */
1426       /* scale indicator bit of the field.                                  */
1427       /*--------------------------------------------------------------------*/
1428       case R_PP16B   :
1429       case R_PPL16B  :
1430       case R_PPN16B  :
1431       case R_PPLN16B :
1432          {
1433             char *sname = (SECT_HDR(s)->s_zeroes == 0) ? 
1434                           SECT_HDR(s)->s_nptr : SNAMECPY(SECT_HDR(s)->s_name);
1436             pp_local = (rp->r_type == R_PPL16B) || (rp->r_type == R_PPLN16B);
1438             /*--------------------------------------------------------------*/
1439             /* READ THE SCALE BIT (16th BIT) AND CREATE 16 BIT CONSTANT OFF */
1440             /*--------------------------------------------------------------*/
1441             objval |= (unpack(data, 1, 64, pp_local ? 28 : 6) << 15);
1443             /*--------------------------------------------------------------*/
1444             /* IF NEGATIVE RELOC TYPE, THEN TREAT CONST OFFSET AS NEGATIVE  */
1445             /*--------------------------------------------------------------*/
1446             if (rp->r_type == R_PPN16B || rp->r_type == R_PPLN16B)
1447             {
1448                objval      = - objval;
1449                rp->r_type -= 010; /* CHANGE THE TYPE TO A NON NEG TYPE.     */
1450             }
1452             objval += reloc_amt;
1454             /*--------------------------------------------------------------*/
1455             /* IF THE ADDRESS STILL FALLS WITHIN AN APPROPRIATE RANGE       */
1456             /*--------------------------------------------------------------*/
1457             if ((objval >= 0x00000000 && objval <= 0x0000ffff) || 
1458                 (objval >= 0x01000000 && objval <= 0x010007ff) )
1459             {
1460                /*-----------------------------------------------------------*/
1461                /* RELOCATE THE 16TH BIT OF THE ADDRESS.                     */
1462                /*-----------------------------------------------------------*/
1463                repack(((objval&0x8000) >> 15), data, 1, 64, pp_local ? 28 : 6);
1464                break;
1465             }
1467             /*--------------------------------------------------------------*/
1468             /* ADDRESS IS OUT OF RANGE.                                     */
1469             /*--------------------------------------------------------------*/
1470             
1471             load_err = E_RELOCENT;
1472             return FALSE;
1473          }
1475       /*--------------------------------------------------------------------*/
1476       /* PP BASE ADDRESS RELOCATION.  BIT 0 IS 0 IF IN DATA RAM, 1 IF IN    */
1477       /* PARAMETER RAM.  THIS CODE ASSUMES THAT WE DO NOT RELOCATE FROM     */
1478       /* PRAM TO DRAM OR FROM DRAM TO PRAM AT LOAD TIME.                    */
1479       /*--------------------------------------------------------------------*/
1480       case R_PPLBASE: pp_local = TRUE;
1481       case R_PPBASE:
1482          {
1483            /*---------------------------------------------------------------*/
1484            /* IF WAS DRAM AND RELOC_AMT IS GREAT ENOUGH TO MOVE INTO PRAM,  */
1485            /* CHANGE TO PRAM                                                */
1486            /*---------------------------------------------------------------*/
1487            if (!objval && reloc_amt > (int)(0x01000000 - 0xC000)) objval = 1;
1489            /*---------------------------------------------------------------*/
1490            /* IF WAS PRAM AND RELOC_AMT IS NEGATIVE AND CAN MOVE INTO DRAM, */
1491            /* CHANGE TO DRAM                                                */
1492            /*---------------------------------------------------------------*/
1493            else if (objval && (-reloc_amt) > (int)(0x01000000 - 0xC000))
1494                objval = 0;
1496            break;
1497          }
1499       /*----------------------------------------------------------------------*/
1500       /* 34010 ONE'S COMPLEMENT RELOCATION.  SUBTRACT INSTEAD OF ADD.         */
1501       /*----------------------------------------------------------------------*/
1502       case R_OCRLONG:
1503          objval -= reloc_amt;
1504          break;
1506       /*----------------------------------------------------------------------*/
1507       /* 34020 WORD-SWAPPED RELOCATION.  SWAP BEFORE RELOCATING.              */
1508       /*----------------------------------------------------------------------*/
1509       case R_GSPOPR32:
1510       case R_OCBD32:
1511           objval  = ((objval >> 16) & 0xFFFF) | (objval << 16); 
1512           objval += (rp->r_type == R_GSPOPR32) ? reloc_amt : -reloc_amt; 
1513           objval  = ((objval >> 16) & 0xFFFF) | (objval << 16);
1514           break; 
1516       /*----------------------------------------------------------------------*/
1517       /* PC-RELATIVE RELOCATIONS.  IN THIS CASE THE RELOCATION AMOUNT         */
1518       /* IS ADJUSTED BY THE PC DIFFERENCE.   IF THIS IS AN INTERNAL           */
1519       /* RELOCATION TO THE CURRENT SECTION, NO ADJUSTMENT IS NEEDED.          */
1520       /*----------------------------------------------------------------------*/
1521       case R_PCRBYTE:
1522       case R_PCRWORD:
1523       case R_GSPPCR16:
1524       case R_GSPPCA16:
1525       case R_PCRLONG:
1526       case R_PCR24:
1527       case R_ANKPCR16:
1528       case R_ANKPCR8:
1529          {
1530             int           shift = 8 * (4 - fieldsz);
1531             unsigned int pcdif = RUN_RELOC_AMOUNT(s);
1533             /*----------------------------------------------------------------*/
1534             /* HANDLE SPECIAL CASES OF JUMPING FROM ABSOLUTE SECTIONS (SPECIAL*/
1535             /* RELOC TYPE) OR TO ABSOLUTE DESTINATION (SYMNDX == -1).  IN     */
1536             /* EITHER CASE, SET THE APPROPRIATE RELOCATION AMOUNT TO 0.       */
1537             /*----------------------------------------------------------------*/
1538             if( rp->r_symndx == -1 )      reloc_amt = 0;
1539             if( rp->r_type == R_GSPPCA16) pcdif = 0;
1541             /*----------------------------------------------------------------*/
1542             /* Handle ankoor's offset where upper 14 (PCR8) and upper 6(PCR16)*/
1543             /* bits of 22 bit address is held in r_disp field of reloc entry  */
1544             /*----------------------------------------------------------------*/
1545             if(rp->r_type == R_ANKPCR8 || rp->r_type == R_ANKPCR16)
1546             {
1547                 shift = 10;
1548                 objval |= rp->r_disp << ((rp->r_type == R_ANKPCR8) ? 8 : 16);
1549             }
1551             reloc_amt -= pcdif;
1553             if (rp->r_type == R_GSPPCR16 || rp->r_type == R_GSPPCA16)
1554                reloc_amt >>= 4;                              /* BITS TO WORDS */
1556             objval  = (int)(objval << shift) >> shift;      /* SIGN EXTEND   */
1557             objval += reloc_amt;
1558             break;
1559          }
1561       /*--------------------------------------------------------------------*/
1562       /* Ankoor page-addressing.  Calculate address from the 22-bit         */
1563       /* value in the relocation field plus the relocation amount. Shift    */
1564       /* out the lower 16 bits.                                             */
1565       /*--------------------------------------------------------------------*/
1566       case R_PARTMS6:
1567           objval = (objval & 0xC0) |
1568                    (((rp->r_disp += reloc_amt) >> 16) & 0x3F);
1569           break;
1571       /*----------------------------------------------------------------------*/
1572       /* 320C30 PAGE-ADDRESSING RELOCATION.  CALCULATE THE ADDRESS FROM       */
1573       /* THE 8-BIT PAGE VALUE IN THE FIELD, THE 16-BIT OFFSET IN THE RELOC    */
1574       /* ENTRY, AND THE RELOCATION AMOUNT.  THEN, STORE THE 8-BIT PAGE        */
1575       /* VALUE OF THE RESULT BACK IN THE FIELD.                               */
1576       /*----------------------------------------------------------------------*/
1577       case R_PARTMS8:
1578           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 16;
1579           break;
1581       /*----------------------------------------------------------------------*/
1582       /* DSP(320) PAGE-ADDRESSING.  CALCULATE ADDRESS FROM THE 16-BIT         */
1583       /* VALUE IN THE RELOCATION FIELD PLUS THE RELOCATION AMOUNT.  OR THE    */
1584       /* TOP 9 BITS OF THIS RESULT INTO THE RELOCATION FIELD.                 */
1585       /*----------------------------------------------------------------------*/
1586       case R_PARTMS9:
1587           objval = (objval & 0xFE00) | 
1588                    (((int)(rp->r_disp + reloc_amt) >> 7) & 0x1FF);
1589           break;
1591       /*----------------------------------------------------------------------*/
1592       /* DSP(320) PAGE-ADDRESSING.  CALCULATE ADDRESS AS ABOVE, AND OR THE    */
1593       /* 7-BIT DISPLACEMENT INTO THE FIELD.                                   */
1594       /*----------------------------------------------------------------------*/
1595       case R_PARTLS7:
1596           objval = (objval & 0x80) | ((rp->r_disp + reloc_amt) & 0x7F);
1597           break;
1599       /*--------------------------------------------------------------------*/
1600       /* Ankoor page-addressing.  Calculate address from the 22-bit         */
1601       /* value in the relocation field plus the relocation amount. Mask off */
1602       /* bits [21:16] and [5:0] to extract a data page within a 64K page    */
1603       /*--------------------------------------------------------------------*/
1604       case R_PARTMID10:
1605           objval = (objval & 0xFC00) |
1606                    (((rp->r_disp += reloc_amt) >> 6) & 0x3FF);
1607           break;
1609       /*--------------------------------------------------------------------*/
1610       /* RR(370) MSB RELOCATION.  CALCULATE ADDRESS FROM THE 16-BIT VALUE   */
1611       /* IN THE RELOCATION ENTRY PLUS THE RELOCATION AMOUNT.  PATCH THE     */
1612       /* MSB OF THE RESULT INTO THE RELOCATION FIELD.                       */
1613       /*--------------------------------------------------------------------*/
1614       case R_HIWORD:
1615           objval += (rp->r_disp += (unsigned short)reloc_amt) >> 8;
1616           break;
1618       /*--------------------------------------------------------------------*/
1619       /* C8+ High byte of 24-bit address.  Calculate address from 24-bit    */
1620       /* value in the relocation entry plus the relocation amount.  Patch   */
1621       /* the MSB of the result into the relocation field.                   */
1622       /*--------------------------------------------------------------------*/
1623       case R_C8PHIBYTE:
1624           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 16;
1625           break;
1627       /*--------------------------------------------------------------------*/
1628       /* C8+ Middle byte of 24-bit address.  Calculate address from 24-bit  */
1629       /* value in the relocation entry plus the relocation amount.  Patch   */
1630       /* the middle byte of the result into the relocation field.           */
1631       /*--------------------------------------------------------------------*/
1632       case R_C8PMIDBYTE:
1633           objval = (int)((objval << 16) + rp->r_disp + reloc_amt) >> 8;
1634           break;
1636       /*--------------------------------------------------------------------*/
1637       /* C8+ Vector Address.  Calculate address from 24-bit value in the    */
1638       /* relocation entry plus the relocation amount.  MSB must be 0xFF     */
1639       /* since interrupt and trap handlers must be programmed in the top-   */
1640       /* most segment of memory.  Patch bottom 16-bits of the result into   */
1641       /* the relocation field.                                              */
1642       /*--------------------------------------------------------------------*/
1643       case R_C8PVECADR:
1644           objval += reloc_amt;
1645           if ((objval & 0xFF0000) != 0xFF0000)
1646           {
1647              /* ERROR */
1648           }
1649           objval &= 0xFFFF;
1650           break;
1652       /*----------------------------------------------------------------------*/
1653       /* C8+ 24-bit Address.  The byte ordering for 24-bit addresses on the   */
1654       /* C8+ is reversed (low, middle, high).  Needs to be unordered, add     */
1655       /* in reloc_amt, then re-ordered.                                       */
1656       /*----------------------------------------------------------------------*/
1657       case R_C8PADR24:
1658           objval = ((objval>>16) | (objval&0xff00) | ((objval&0xff)<<16));
1659           objval += reloc_amt;
1660           objval = ((objval>>16) | (objval&0xff00) | ((objval&0xff)<<16));
1661           break;
1663       /*----------------------------------------------------------------------*/
1664       /* DSP(320) 13-BIT CONSTANT.  RELOCATE ONLY THE LOWER 13 BITS OF THE    */
1665       /* FIELD.                                                               */
1666       /*----------------------------------------------------------------------*/
1667       case R_REL13:
1668           objval = (objval & 0xE000) | ((objval + reloc_amt) & 0x1FFF);
1669           break;
1671       /*--------------------------------------------------------------------*/
1672       /* ANKOOR 22-bit extended address.  Calculate address by masking      */
1673       /* off the opcode and OR in the lower 16-bit constant + the           */
1674       /* amount.                                                            */
1675       /*--------------------------------------------------------------------*/
1676       case R_REL22:
1677          {
1678             unsigned int obj_hi = unpack(data  , 16, 16, 0);
1679             unsigned int obj_lo = unpack(data+2, 16, 16, 0);
1681             /*--------------------------------------------------------------*/
1682             /* BUILD THE OFFSET TO BE RELOCATED.                            */
1683             /*--------------------------------------------------------------*/
1684             objval = ((obj_hi & 0x003F) << 16) | (obj_lo & 0xFFFF);
1686             /*--------------------------------------------------------------*/
1687             /* Calculate displacement                                       */
1688             /*--------------------------------------------------------------*/
1689             objval += reloc_amt;
1691             /*--------------------------------------------------------------*/
1692             /* REPACK THE RELOCATED VALUE BACK IN THE OBJECT VALUE.         */
1693             /*--------------------------------------------------------------*/
1694             obj_hi = (obj_hi & 0xFFC0) | ((objval & 0x3F0000) >> 16);
1695             obj_lo = objval & 0xFFFF;
1696             repack(obj_hi, data  , 16, 16, 0);
1697             repack(obj_lo, data+2, 16, 16, 0);
1699             return TRUE;
1700          }
1702       /*--------------------------------------------------------------------*/
1703       /* DSP, LEAD 23-bit extended address.  Calculate address by masking   */
1704       /* off the opcode and OR in the lower 16-bit constant + the           */
1705       /* amount.                                                            */
1706       /*--------------------------------------------------------------------*/
1707       case R_REL23:
1708          {
1709             unsigned int obj_hi = unpack(data  , 16, 16, 0);
1710             unsigned int obj_lo = unpack(data+2, 16, 16, 0);
1712             /*--------------------------------------------------------------*/
1713             /* BUILD THE OFFSET TO BE RELOCATED.                            */
1714             /*--------------------------------------------------------------*/
1715             objval = ((obj_hi & 0x007F) << 16) | (obj_lo & 0xFFFF);
1717             /*--------------------------------------------------------------*/
1718             /* Calculate displacement                                       */
1719             /*--------------------------------------------------------------*/
1720             objval += reloc_amt;
1722             /*--------------------------------------------------------------*/
1723             /* REPACK THE RELOCATED VALUE BACK IN THE OBJECT VALUE.         */
1724             /*--------------------------------------------------------------*/
1725             obj_hi = (obj_hi & 0xFF80) | ((objval & 0x7F0000) >> 16);
1726             obj_lo = objval & 0xFFFF;
1727             repack(obj_hi, data  , 16, 16, 0);
1728             repack(obj_lo, data+2, 16, 16, 0);
1730             return TRUE;
1731          }
1734       /*----------------------------------------------------------------------*/
1735       /* PRISM (370/16) code label relocation.  Convert word address to byte  */
1736       /* address, add in relocation, convert back to word address.            */
1737       /*----------------------------------------------------------------------*/
1738       case R_LABCOD:
1739           objval = ((objval << 1) + reloc_amt) >> 1;
1740           break;
1741    }
1743    /*-------------------------------------------------------------------------*/
1744    /* PACK THE RELOCATED FIELD BACK INTO THE OBJECT DATA.                     */
1745    /*-------------------------------------------------------------------------*/
1746    repack(objval, data, fieldsz, wordsz, offset + BIT_OFFSET(rp->r_vaddr));
1747    return TRUE;
1748
1751 /******************************************************************************/
1752 /*                                                                            */
1753 /* RELOC_READ() - Read a single relocation entry.                             */
1754 /*                                                                            */
1755 /******************************************************************************/
1756 #if FILE_BASED
1757 int reloc_read(RELOC *rptr)
1758 #else
1759 int reloc_read(RELOC *rptr, unsigned int offset)
1760 #endif
1762 #if COFF_VERSION_1 || COFF_VERSION_2
1763    /*------------------------------------------------------------------------*/
1764    /* THE FOLLOWING UNION IS USED TO READ IN VERSION 0 OR 1 RELOC ENTRIES    */
1765    /*------------------------------------------------------------------------*/
1766    /* THE FORMAT OF RELOCATION ENTRIES CHANGED BETWEEN COFF VERSIONS 0 AND 1.*/
1767    /* VERSION 0 HAS A 16 BIT SYMBOL INDEX, WHILE VERSION 1 HAS A 32 BIT INDX.*/
1768    /*------------------------------------------------------------------------*/
1769    union { RELOC new_c; RELOC_OLD old; } input_entry;
1770 #if FILE_BASED
1771    if (fread(&input_entry, RELSZ_IN(coff_version), 1, fin) != 1)
1772       { load_err = E_FILE; return FALSE; }
1773 #else
1774         mem_copy((void*)&input_entry, (void*)&gRxBuffer[offset], RELSZ_IN(coff_version));
1775 #endif
1776    /*------------------------------------------------------------------------*/
1777    /* IF LOADING A VERSION 0 FILE, TRANSLATE ENTRY TO VERSION 1 FORMAT.      */
1778    /* (THIS COULD BE SIMPLER - ALL THE SWAPS EXCEPT FOR THE SYMBOL INDEX     */
1779    /* COULD BE DONE AFTER THE TRANSLATION - BUT THIS SEEMS TO BE CLEARER)    */
1780    /*------------------------------------------------------------------------*/
1781    if (ISCOFF_0(coff_version))
1782    {
1783       if (byte_swapped)
1784       {
1785          swap4byte(&input_entry.old.r_vaddr);
1786          swap2byte(&input_entry.old.r_type);
1788          /* if a field reloc, fields are chars, so don't swap */
1789          if (!isfldrel(input_entry.old.r_type))
1790          {
1791              swap2byte(&input_entry.old.r_symndx);
1792              swap2byte(&input_entry.old.r_disp);
1793          }
1794       }
1796       rptr->r_vaddr  = input_entry.old.r_vaddr;
1797       rptr->r_symndx = input_entry.old.r_symndx;
1798       rptr->r_disp   = input_entry.old.r_disp;
1799       rptr->r_type   = input_entry.old.r_type;
1800    }
1801    else
1802    {
1803       *rptr = input_entry.new_c;
1805       if (byte_swapped)
1806       {
1807          swap4byte(&rptr->r_vaddr); 
1808          swap2byte(&rptr->r_type);
1810          /* Again, if a field reloc, fields are chars, so don't swap */
1811          if (!isfldrel(rptr->r_type))
1812          {
1813              swap4byte(&rptr->r_symndx);
1814              swap2byte(&rptr->r_disp);  
1815          }
1816       }
1817    }
1819 #else
1820    /*-------------------------------------------------------------------------*/
1821    /* READ IN AND BYTE SWAP AN VERSION 0 RELOC ENTRY                          */
1822    /*-------------------------------------------------------------------------*/
1823    if (fread(rptr, RELSZ, 1, fin) != 1) { load_err = E_FILE; return FALSE; }
1825    if (byte_swapped)
1826    {
1827       swap4byte(&rptr->r_vaddr);
1828       swap2byte(&rptr->r_type);  
1830       /* If a field reloc, fields are chars, so don't swap */
1831       if (!isfldrel(rptr->r_type))
1832       {
1833           swap2byte(&rptr->r_symndx);
1834           swap2byte(&rptr->r_disp);
1835       }
1836    }
1837 #endif
1839    return TRUE;
1843 #endif
1844 /*************************************************************************/
1845 /*                                                                       */
1846 /*   RELOC_SIZE()-                                                       */
1847 /*      Return the field size of a relocation type.                      */
1848 /*                                                                       */
1849 /*************************************************************************/
1851 int reloc_size(int type)
1853    switch (type)
1854    {
1855        case R_PPBASE:
1856        case R_PPLBASE:      return 1;
1858        case R_HIWORD:
1859        case R_C8PHIBYTE:
1860        case R_C8PMIDBYTE:
1861        case R_RELBYTE:
1862        case R_PCRBYTE:
1863        case R_RRNREG:
1864        case R_RRRELREG:
1865        case R_ANKPCR8:
1866        case R_PARTLS6:
1867        case R_PARTMS6:
1868        case R_PARTLS7:      return 8;
1870        case R_PP15:
1871        case R_PP15W:
1872        case R_PP15H:
1873        case R_PP16B:
1874        case R_PPN15:
1875        case R_PPN15W:
1876        case R_PPN15H:
1877        case R_PPN16B:
1878        case R_PPL15:
1879        case R_PPL15W:
1880        case R_PPL15H:
1881        case R_PPL16B:
1882        case R_PPLN15:
1883        case R_PPLN15W:
1884        case R_PPLN15H:
1885        case R_PPLN16B:      return 15;
1887        case R_LABCOD:
1888        case R_RELWORD:
1889        case R_PCRWORD:
1890        case R_ANKPCR16:
1891        case R_GSPPCR16:
1892        case R_GSPPCA16:
1893        case R_PARTLS16:
1894        case R_PARTMS8:
1895        case R_PARTMS9:
1896        case R_PARTMID10:
1897        case R_PARTMS16:
1898        case R_REL22:
1899        case R_REL13:        
1900        case R_C8PVECADR:    return 16;
1902        case R_REL24:
1903        case R_PCR24:
1904        case R_PCR24W:
1905       case R_C8PADR24:      return 24;
1907        case R_MPPCR:
1908        case R_GSPOPR32:
1909        case R_RELLONG:
1910        case R_PCRLONG:
1911        case R_OCBD32:
1912        case R_OCRLONG:
1913        case R_DIR32:        return 32;
1915        default:             return 0;
1916    }
1920 /*************************************************************************/
1921 /*                                                                       */
1922 /*   RELOC_OFFSET()-                                                     */
1923 /*      Return the offset of a relocation type field.  The value of      */
1924 /*      offset should be the bit offset of the LSB of the field in       */
1925 /*      little-endian mode.                                              */
1926 /*                                                                       */
1927 /*************************************************************************/
1929 int reloc_offset(int type)
1931    switch (type)
1932    {
1933        case R_PP15    :
1934        case R_PP15W   :
1935        case R_PP15H   :
1936        case R_PP16B   :
1937        case R_PPN15   :
1938        case R_PPN15W  :
1939        case R_PPN15H  :
1940        case R_PPN16B  :
1941        case R_PPLBASE :     return 22;
1943        case R_PPL15   :
1944        case R_PPL15W  :
1945        case R_PPL15H  :
1946        case R_PPL16B  :
1947        case R_PPLN15  :
1948        case R_PPLN15W :
1949        case R_PPLN15H :
1950        case R_PPLN16B :
1951        case R_PPBASE  :     return 0;
1953        default        :     return 0;
1954    }
1958 /*************************************************************************/
1959 /*                                                                       */
1960 /*   RELOC_STOP() -                                                      */
1961 /*      Return the number of bits to read for a relocation type.         */
1962 /*                                                                       */
1963 /*************************************************************************/
1965 int reloc_stop(int type)
1967    switch (type)
1968    {
1969        case R_PPBASE  :
1970        case R_PPLBASE :
1972        case R_PP15    :
1973        case R_PP15W   :
1974        case R_PP15H   :
1975        case R_PP16B   :
1977        case R_PPL15   :
1978        case R_PPL15W  :
1979        case R_PPL15H  :
1980        case R_PPL16B  :
1982        case R_PPN15   :
1983        case R_PPN15W  :
1984        case R_PPN15H  :
1985        case R_PPN16B  :
1987        case R_PPLN15  :
1988        case R_PPLN15W :
1989        case R_PPLN15H :
1990        case R_PPLN16B :   return 64;
1992        default       :    return WORDSZ * 8;
1993    }
1997 #if 0
1998 /******************************************************************************/
1999 /*                                                                            */
2000 /* SYM_RELOC_AMOUNT() - Determine the amount of relocation for a particular   */
2001 /*                      relocation entry.  Search the relocation symbol table */
2002 /*                      for the referenced symbol, and return the amount from */
2003 /*                      the table.                                            */
2004 /*                                                                            */
2005 /******************************************************************************/
2006 int sym_reloc_amount(RELOC *rp)
2008    int index = rp->r_symndx;
2010    int i = 0,
2011        j = reloc_sym_index - 1;
2013    /*-------------------------------------------------------------------------*/
2014    /* THIS IS A SIMPLE BINARY SEARCH (THE RELOC TABLE IS ALWAYS SORTED).      */
2015    /*-------------------------------------------------------------------------*/
2016    while (i <= j)
2017    {
2018       int m = (i + j) / 2;
2019       if      (reloc_tab[m].rt_index < index) i = m + 1;
2020       else if (reloc_tab[m].rt_index > index) j = m - 1;
2021       else return reloc_tab[m].rt_disp;                              /* FOUND */
2022    }
2024    /*-------------------------------------------------------------------------*/
2025    /* IF NOT FOUND, SYMBOL WAS NOT RELOCATED.                                 */
2026    /*-------------------------------------------------------------------------*/
2027    return 0;
2030 #endif
2032 /******************************************************************************/
2033 /*                                                                            */
2034 /*  UNPACK() - Extract a relocation field from object bytes and convert into  */
2035 /*             a int so it can be relocated.                                 */
2036 /*                                                                            */
2037 /******************************************************************************/
2038 unsigned int unpack(unsigned char *data, int fieldsz, int wordsz, int bit_offset)
2040    register int  i;
2041    unsigned int objval;
2042    int           start;                       /* MS byte with reloc data      */
2043    int           stop;                        /* LS byte with reloc data      */
2044    int           r  = bit_offset & 7;         /* num unused LS bits in stop   */
2045    int           l  = 8 - r;                  /* num used   MS bits in stop   */
2046    int           tr = ((bit_offset+fieldsz-1) & 7)+1; /* # LS bits in strt*/
2047    int           tl = 8 - tr;                 /* num unused MS bits in start  */
2049    start = (big_e_target ? (wordsz-fieldsz-bit_offset) : 
2050                            (bit_offset+fieldsz-1)) >>3;
2051    stop  = (big_e_target ? (wordsz-bit_offset-1) : bit_offset) >>3;
2053    if (start == stop) return (data[stop] >> r) & ((0x1 << fieldsz) - 0x1);
2055    objval = (unsigned)((data[start] << tl) & 0xFF) >> tl;
2056    
2057    if (big_e_target) 
2058          for (i=start+1; i<stop; ++i) objval = (objval << 8) | data[i];
2059    else  for (i=start-1; i>stop; --i) objval = (objval << 8) | data[i];
2060    
2061    return (objval << l) | (data[stop] >> r);
2066 /******************************************************************************/
2067 /*                                                                            */
2068 /* REPACK() - Encode a binary relocated field back into the object data.      */
2069 /*                                                                            */
2070 /******************************************************************************/
2071 void repack(unsigned int objval, unsigned char *data, int fieldsz,
2072             int  wordsz, int bit_offset)
2074    register int  i;
2075    int           start;                      /* MS byte with reloc data       */
2076    int           stop;                       /* LS byte with reloc data       */
2077    int           r     = bit_offset & 7;     /* num unused LS bits in stop    */
2078    int           l     = 8 - r;              /* num used   MS bits in stop    */
2079    int           tr    = ((bit_offset+fieldsz-1) & 7)+1; /* # LS bits in strt */
2080    unsigned int mask  = (1ul << fieldsz) - 1ul;
2082    if (fieldsz < sizeof(objval)) objval &= mask;
2083    
2084    start = (big_e_target ? (wordsz-fieldsz-bit_offset) : 
2085                            (bit_offset+fieldsz-1)) >>3;
2086    stop  = (big_e_target ? (wordsz-bit_offset-1) : bit_offset) >>3;
2088    if (start == stop)
2089    {
2090        data[stop] &= ~(mask << r);
2091        data[stop] |= (objval << r); 
2092        return;
2093    }
2095    data[start] &= ~((1<<tr)-1);
2096    data[stop]  &=  ((1<< r)-1);
2097    data[stop]  |= (objval << r); 
2098    objval     >>= l;
2100    if (big_e_target) 
2101         for (i = stop - 1; i > start; objval >>= 8) data[i--] = objval;
2102    else for (i = stop + 1; i < start; objval >>= 8) data[i++] = objval;
2103    
2104    data[start] |= objval; 
2108 /******************************************************************************/
2109 /*                                                                            */
2110 /* CLOAD_LINENO() - Read in, swap, and relocate line number entries.  This    */
2111 /*                  function is not called directly by the loader, but by the */
2112 /*                  application when it needs to read in line number entries. */
2113 /*                                                                            */
2114 /******************************************************************************/
2115 int cload_lineno(int filptr, int count, LINENO *lptr, int scnum) 
2117 /*   int    filptr;                      WHERE TO READ FROM                  */
2118 /*   int     count;                       HOW MANY TO READ                    */
2119 /*   LINENO *lptr;                        WHERE TO PUT THEM                   */
2120 /*   int     scnum;                       SECTION NUMBER OF THESE ENTRIES     */
2122     int i;
2124     /*------------------------------------------------------------------------*/
2125     /* READ IN THE REQUESTED NUMBER OF LINE NUMBER ENTRIES AS A BLOCK.        */
2126     /*------------------------------------------------------------------------*/
2127 #if FILE_BASED
2128     if (fseek(fin, filptr, 0) != 0) { load_err = E_FILE; return FALSE; }
2129     for (i = 0; i < count; i++)
2130         if (fread(lptr + i, 1, LINESZ, fin) != LINESZ) 
2131                                     { load_err = E_FILE; return FALSE; }
2132 #else
2133         for (i = 0; i < count; i++)
2134         mem_copy((void*)(lptr+i), (void*)&gRxBuffer[filptr + i*LINESZ], LINESZ);
2135 #endif
2136     /*------------------------------------------------------------------------*/
2137     /* SWAP AND RELOCATE EACH ENTRY, AS NECESSARY.                            */
2138     /*------------------------------------------------------------------------*/
2139     if (byte_swapped || RUN_RELOC_AMOUNT(scnum - 1))
2140        for (i = 0; i < count; i++, lptr++)
2141        {
2142           if (byte_swapped)
2143           {
2144               swap2byte(&lptr->l_lnno);
2145               swap4byte(&lptr->l_addr.l_paddr);
2146           }
2148           if (lptr->l_lnno != 0) 
2149              lptr->l_addr.l_paddr += RUN_RELOC_AMOUNT(scnum - 1);
2150        }
2151     
2152     return TRUE;
2156 /******************************************************************************/
2157 /*                                                                            */
2158 /*  SWAP4BYTE() - Swap the order of bytes in a int.                          */
2159 /*                                                                            */
2160 /******************************************************************************/
2161 void swap4byte(void *addr)
2163    unsigned int *value = (unsigned int *)addr;
2164    unsigned int temp1, temp2, temp3, temp4;
2166    temp1 = (*value)       & 0xFF;
2167    temp2 = (*value >> 8)  & 0xFF;
2168    temp3 = (*value >> 16) & 0xFF;
2169    temp4 = (*value >> 24) & 0xFF;
2171    *value = (temp1 << 24) | (temp2 << 16) | (temp3 << 8) | temp4;
2175 /******************************************************************************/
2176 /*                                                                            */
2177 /*  SWAP2BYTE() - Swap the order of bytes in a short.                         */
2178 /*                                                                            */
2179 /******************************************************************************/
2180 void swap2byte(void *addr)
2182    unsigned short *value = (unsigned short *)addr;
2183    unsigned short temp1,temp2;
2185    temp1 = temp2 = *value;
2186    *value = ((temp2 & 0xFF) << 8) | ((temp1 >> 8) & 0xFF);