Subversion Repositories Kolibri OS

Rev

Rev 5191 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /* COFF information for TI COFF support.  Definitions in this file should be
  2.    customized in a target-specific file, and then this file included (see
  3.    tic54x.h for an example).
  4.    
  5.    Copyright (C) 2000-2015 Free Software Foundation, Inc.
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 3 of the License, or
  10.    (at your option) any later version.
  11.    
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.    
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  20.    MA 02110-1301, USA.  */
  21.  
  22. #ifndef COFF_TI_H
  23. #define COFF_TI_H
  24.  
  25. /* Note "coff/external.h is not used because TI adds extra fields to the structures.  */
  26.  
  27. /********************** FILE HEADER **********************/
  28.  
  29. struct external_filehdr
  30.   {
  31.     char f_magic[2];    /* magic number                 */
  32.     char f_nscns[2];    /* number of sections           */
  33.     char f_timdat[4];   /* time & date stamp            */
  34.     char f_symptr[4];   /* file pointer to symtab       */
  35.     char f_nsyms[4];    /* number of symtab entries     */
  36.     char f_opthdr[2];   /* sizeof(optional hdr)         */
  37.     char f_flags[2];    /* flags                        */
  38.     char f_target_id[2];    /* magic no. (TI COFF-specific) */
  39.   };
  40.  
  41. /* COFF0 has magic number in f_magic, and omits f_target_id from the file
  42.    header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2
  43.    and the target-specific magic number is found in f_target_id */
  44.  
  45. #define TICOFF0MAGIC    TI_TARGET_ID
  46. #define TICOFF1MAGIC    0x00C1
  47. #define TICOFF2MAGIC    0x00C2
  48. #define TICOFF_AOUT_MAGIC    0x0108 /* magic number in optional header */
  49. #define TICOFF          1 /* customize coffcode.h */
  50.  
  51. /* The target_id field changes depending on the particular CPU target */
  52. /* for COFF0, the target id appeared in f_magic, where COFFX magic is now */
  53. #ifndef TI_TARGET_ID
  54. #error "TI_TARGET_ID needs to be defined for your CPU"
  55. #endif
  56.  
  57. /* Which bfd_arch to use... */
  58. #ifndef TICOFF_TARGET_ARCH
  59. #error "TICOFF_TARGET_ARCH needs to be defined for your CPU"
  60. #endif
  61.  
  62. #ifndef TICOFF_TARGET_MACHINE_GET
  63. #define TICOFF_TARGET_MACHINE_GET(FLAGS) 0
  64. #endif
  65.  
  66. #ifndef TICOFF_TARGET_MACHINE_SET
  67. #define TICOFF_TARGET_MACHINE_SET(FLAGSP, MACHINE)
  68. #endif
  69.  
  70. /* Default to COFF2 for file output */
  71. #ifndef TICOFF_DEFAULT_MAGIC
  72. #define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC
  73. #endif
  74.  
  75. /* This value is made available in the rare case where a bfd is unavailable */
  76. #ifndef OCTETS_PER_BYTE_POWER
  77. #error "OCTETS_PER_BYTE_POWER not defined for this CPU"
  78. #else
  79. #define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
  80. #endif
  81.  
  82. /* default alignment is on a byte (not octet!) boundary */
  83. #ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER
  84. #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
  85. #endif
  86.  
  87. /* TI COFF encodes the section alignment in the section header flags */
  88. #define COFF_ALIGN_IN_SECTION_HEADER 1
  89. #define COFF_ALIGN_IN_S_FLAGS 1
  90. /* requires a power-of-two argument */
  91. #define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8))
  92. /* result is a power of two */
  93. #define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF)
  94.  
  95. #define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0)
  96. #define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01)
  97.  
  98. #define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC)
  99. #define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID)
  100. #define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID)
  101.  
  102. /* we need to read/write an extra field in the coff file header */
  103. #ifndef COFF_ADJUST_FILEHDR_IN_POST
  104. #define COFF_ADJUST_FILEHDR_IN_POST(abfd, src, dst) \
  105.   do                                                                    \
  106.     {                                                                   \
  107.       if (!COFF0_P (abfd))                                              \
  108.         ((struct internal_filehdr *)(dst))->f_target_id =               \
  109.           H_GET_16 (abfd, ((FILHDR *)(src))->f_target_id);              \
  110.     }                                                                   \
  111.   while (0)
  112. #endif
  113.  
  114. #ifndef COFF_ADJUST_FILEHDR_OUT_POST
  115. #define COFF_ADJUST_FILEHDR_OUT_POST(abfd, src, dst) \
  116.   do                                                                     \
  117.     {                                                                    \
  118.       if (!COFF0_P (abfd))                                               \
  119.         H_PUT_16 (abfd, ((struct internal_filehdr *)(src))->f_target_id, \
  120.                  ((FILHDR *)(dst))->f_target_id);                        \
  121.     }                                                                    \
  122.   while (0)
  123. #endif
  124.  
  125. #define FILHDR  struct external_filehdr
  126. #define FILHSZ  22
  127. #define FILHSZ_V0 20                /* COFF0 omits target_id field */
  128.  
  129. /* File header flags */
  130. #define F_RELFLG        (0x0001)
  131. #define F_EXEC          (0x0002)
  132. #define F_LNNO          (0x0004)
  133. #define F_VERS          (0x0010) /* TMS320C4x code */
  134. /* F_LSYMS needs to be redefined in your source file */
  135. #define F_LSYMS_TICOFF  (0x0010) /* normal COFF is 0x8 */
  136.  
  137. #define F_10            0x00    /* file built for TMS320C1x devices */
  138. #define F_20            0x10    /* file built for TMS320C2x devices */
  139. #define F_25            0x20    /* file built for TMS320C2x/C5x devices */
  140. #define F_LENDIAN       0x0100  /* 16 bits/word, LSB first */
  141. #define F_SYMMERGE      0x1000  /* duplicate symbols were removed */
  142.  
  143. /********************** OPTIONAL HEADER **********************/
  144.  
  145.  
  146. typedef struct
  147. {
  148.   char  magic[2];               /* type of file (0x108)                 */
  149.   char  vstamp[2];              /* version stamp                        */
  150.   char  tsize[4];               /* text size in bytes, padded to FW bdry*/
  151.   char  dsize[4];               /* initialized data "  "                */
  152.   char  bsize[4];               /* uninitialized data "   "             */
  153.   char  entry[4];               /* entry pt.                            */
  154.   char  text_start[4];          /* base of text used for this file */
  155.   char  data_start[4];          /* base of data used for this file */
  156. }
  157. AOUTHDR;
  158.  
  159.  
  160. #define AOUTHDRSZ 28
  161. #define AOUTSZ 28
  162.  
  163.  
  164. /********************** SECTION HEADER **********************/
  165. /* COFF0, COFF1 */
  166. struct external_scnhdr_v01 {
  167.         char            s_name[8];      /* section name                 */
  168.         char            s_paddr[4];     /* physical address, aliased s_nlib */
  169.         char            s_vaddr[4];     /* virtual address              */
  170.         char            s_size[4];      /* section size (in WORDS)      */
  171.         char            s_scnptr[4];    /* file ptr to raw data for section */
  172.         char            s_relptr[4];    /* file ptr to relocation       */
  173.         char            s_lnnoptr[4];   /* file ptr to line numbers     */
  174.         char            s_nreloc[2];    /* number of relocation entries */
  175.         char            s_nlnno[2];     /* number of line number entries*/
  176.         char            s_flags[2];     /* flags                        */
  177.         char            s_reserved[1];  /* reserved                     */
  178.         char            s_page[1];      /* section page number (LOAD)   */
  179. };
  180.  
  181. /* COFF2 */
  182. struct external_scnhdr {
  183.         char            s_name[8];      /* section name                 */
  184.         char            s_paddr[4];     /* physical address, aliased s_nlib */
  185.         char            s_vaddr[4];     /* virtual address              */
  186.         char            s_size[4];      /* section size (in WORDS)      */
  187.         char            s_scnptr[4];    /* file ptr to raw data for section */
  188.         char            s_relptr[4];    /* file ptr to relocation       */
  189.         char            s_lnnoptr[4];   /* file ptr to line numbers     */
  190.         char            s_nreloc[4];    /* number of relocation entries */
  191.         char            s_nlnno[4];     /* number of line number entries*/
  192.         char            s_flags[4];     /* flags                        */
  193.         char            s_reserved[2];  /* reserved                     */
  194.         char            s_page[2];      /* section page number (LOAD)   */
  195. };
  196.  
  197. /*
  198.  * Special section flags
  199.  */
  200.  
  201. /* TI COFF defines these flags;
  202.    STYP_CLINK: the section should be excluded from the final
  203.    linker output if there are no references found to any symbol in the section
  204.    STYP_BLOCK: the section should be blocked, i.e. if the section would cross
  205.    a page boundary, it is started at a page boundary instead.
  206.    TI COFF puts the section alignment power of two in the section flags
  207.    e.g. 2**N is alignment, flags |= (N & 0xF) << 8
  208. */
  209. #define STYP_CLINK      (0x4000)
  210. #define STYP_BLOCK      (0x1000)
  211. #define STYP_ALIGN      (0x0F00) /* TI COFF stores section alignment here */
  212.  
  213. #define SCNHDR_V01 struct external_scnhdr_v01
  214. #define SCNHDR struct external_scnhdr
  215. #define SCNHSZ_V01 40                  /* for v0 and v1 */
  216. #define SCNHSZ 48
  217.  
  218. /* COFF2 changes the offsets and sizes of these fields
  219.    Assume we're dealing with the COFF2 scnhdr structure, and adjust
  220.    accordingly.  Note: The GNU C versions of some of these macros
  221.    are necessary in order to avoid compile time warnings triggered
  222.    gcc's array bounds checking.  The PUT_SCNHDR_PAGE macro also has
  223.    the advantage on not evaluating LOC twice.  */
  224.  
  225. #define GET_SCNHDR_NRELOC(ABFD, LOC) \
  226.   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, LOC))
  227. #define PUT_SCNHDR_NRELOC(ABFD, VAL, LOC) \
  228.   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, LOC))
  229. #ifdef __GNUC__
  230. #define GET_SCNHDR_NLNNO(ABFD, LOC) \
  231.   ({ \
  232.     int nlnno;          \
  233.     char * ptr = (LOC); \
  234.     if (COFF2_P (ABFD)) \
  235.       nlnno = H_GET_32 (ABFD, ptr); \
  236.     else \
  237.       nlnno = H_GET_16 (ABFD, ptr - 2); \
  238.     nlnno; \
  239.   })
  240. #define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
  241.   do \
  242.     { \
  243.       char * ptr = (LOC); \
  244.       if (COFF2_P (ABFD)) \
  245.         H_PUT_32 (ABFD, VAL, ptr); \
  246.       else \
  247.         H_PUT_16 (ABFD, VAL, ptr - 2); \
  248.     } \
  249.   while (0)
  250. #define GET_SCNHDR_FLAGS(ABFD, LOC) \
  251.   ({ \
  252.     int flags; \
  253.     char * ptr = (LOC); \
  254.     if (COFF2_P (ABFD)) \
  255.       flags = H_GET_32 (ABFD, ptr); \
  256.     else \
  257.       flags = H_GET_16 (ABFD, ptr - 4); \
  258.     flags; \
  259.   })
  260. #define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
  261.   do \
  262.     { \
  263.       char * ptr = (LOC); \
  264.       if (COFF2_P (ABFD)) \
  265.         H_PUT_32 (ABFD, VAL, ptr); \
  266.       else \
  267.         H_PUT_16 (ABFD, VAL, ptr - 4); \
  268.     } \
  269.   while (0)
  270. #define GET_SCNHDR_PAGE(ABFD, LOC) \
  271.   ({ \
  272.     unsigned page; \
  273.     char * ptr = (LOC); \
  274.     if (COFF2_P (ABFD)) \
  275.       page = H_GET_16 (ABFD, ptr); \
  276.     else \
  277.       page = (unsigned) H_GET_8 (ABFD, ptr - 7); \
  278.     page; \
  279.   })
  280. /* On output, make sure that the "reserved" field is zero.  */
  281. #define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
  282.   do \
  283.     { \
  284.       char * ptr = (LOC); \
  285.       if (COFF2_P (ABFD)) \
  286.         H_PUT_16 (ABFD, VAL, ptr); \
  287.       else \
  288.         { \
  289.           H_PUT_8 (ABFD, VAL, ptr - 7); \
  290.           H_PUT_8 (ABFD, 0, ptr - 8); \
  291.         } \
  292.     } \
  293.   while (0)
  294. #else
  295. #define GET_SCNHDR_NLNNO(ABFD, LOC) \
  296.   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 2))
  297. #define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
  298.   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 2))
  299. #define GET_SCNHDR_FLAGS(ABFD, LOC) \
  300.   (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 4))
  301. #define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
  302.   (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 4))
  303. #define GET_SCNHDR_PAGE(ABFD, LOC) \
  304.   (COFF2_P (ABFD) ? H_GET_16 (ABFD, LOC) : (unsigned) H_GET_8 (ABFD, (LOC) - 7))
  305. /* On output, make sure that the "reserved" field is zero.  */
  306. #define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
  307.   (COFF2_P (ABFD) \
  308.    ? H_PUT_16 (ABFD, VAL, LOC) \
  309.    : H_PUT_8 (ABFD, VAL, (LOC) - 7), H_PUT_8 (ABFD, 0, (LOC) - 8))
  310. #endif
  311.  
  312.  
  313. /* TI COFF stores section size as number of bytes (address units, not octets),
  314.    so adjust to be number of octets, which is what BFD expects */
  315. #define GET_SCNHDR_SIZE(ABFD, SZP) \
  316.   (H_GET_32 (ABFD, SZP) * bfd_octets_per_byte (ABFD))
  317. #define PUT_SCNHDR_SIZE(ABFD, SZ, SZP) \
  318.   H_PUT_32 (ABFD, (SZ) / bfd_octets_per_byte (ABFD), SZP)
  319.  
  320. #define COFF_ADJUST_SCNHDR_IN_POST(ABFD, EXT, INT) \
  321.   do                                                                    \
  322.     {                                                                   \
  323.       ((struct internal_scnhdr *)(INT))->s_page =                       \
  324.         GET_SCNHDR_PAGE (ABFD, ((SCNHDR *)(EXT))->s_page);              \
  325.     }                                                                   \
  326.    while (0)
  327.  
  328. /* The entire scnhdr may not be assigned.
  329.    Ensure that everything is initialized.  */
  330. #define COFF_ADJUST_SCNHDR_OUT_PRE(ABFD, INT, EXT)      \
  331.   do                                                    \
  332.     {                                                   \
  333.       memset((EXT), 0, sizeof (SCNHDR));                \
  334.     }                                                   \
  335.   while (0)
  336.  
  337. /* The line number and reloc overflow checking in coff_swap_scnhdr_out in
  338.    coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc.
  339.    Due to different sized v0/v1/v2 section headers, we have to re-write these
  340.    fields.
  341.  */
  342. #define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT) \
  343.   do                                                                       \
  344.     {                                                                      \
  345.       PUT_SCNHDR_NLNNO (ABFD, ((struct internal_scnhdr *)(INT))->s_nlnno,  \
  346.                         ((SCNHDR *)(EXT))->s_nlnno);                       \
  347.       PUT_SCNHDR_NRELOC (ABFD, ((struct internal_scnhdr *)(INT))->s_nreloc,\
  348.                          ((SCNHDR *)(EXT))->s_nreloc);                     \
  349.       PUT_SCNHDR_FLAGS (ABFD, ((struct internal_scnhdr *)(INT))->s_flags,  \
  350.                         ((SCNHDR *)(EXT))->s_flags);                       \
  351.       PUT_SCNHDR_PAGE (ABFD, ((struct internal_scnhdr *)(INT))->s_page,    \
  352.                        ((SCNHDR *)(EXT))->s_page);                         \
  353.     }                                                                      \
  354.    while (0)
  355.  
  356. /*
  357.  * names of "special" sections
  358.  */
  359. #define _TEXT   ".text"
  360. #define _DATA   ".data"
  361. #define _BSS    ".bss"
  362. #define _CINIT  ".cinit"            /* initialized C data */
  363. #define _SCONST  ".const"           /* constants */
  364. #define _SWITCH ".switch"           /* switch tables */
  365. #define _STACK  ".stack"            /* C stack */
  366. #define _SYSMEM ".sysmem"           /* used for malloc et al. syscalls */
  367.  
  368. /********************** LINE NUMBERS **********************/
  369.  
  370. /* 1 line number entry for every "breakpointable" source line in a section.
  371.  * Line numbers are grouped on a per function basis; first entry in a function
  372.  * grouping will have l_lnno = 0 and in place of physical address will be the
  373.  * symbol table index of the function name.
  374.  */
  375. struct external_lineno {
  376.   union {
  377.     char l_symndx[4];   /* function name symbol index, iff l_lnno == 0*/
  378.     char l_paddr[4];    /* (physical) address of line number    */
  379.   } l_addr;
  380.   char l_lnno[2];       /* line number          */
  381. };
  382.  
  383. #define LINENO  struct external_lineno
  384. #define LINESZ  6
  385.  
  386.  
  387. /********************** SYMBOLS **********************/
  388.  
  389. /* NOTE: this is what a local label looks like in assembly source; what it
  390.    looks like in COFF output is undefined */
  391. #define TICOFF_LOCAL_LABEL_P(NAME) \
  392. ((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \
  393.  || NAME[strlen(NAME)-1] == '?')
  394.  
  395. #define E_SYMNMLEN      8       /* # characters in a symbol name        */
  396. #define E_FILNMLEN      14      /* # characters in a file name          */
  397. #define E_DIMNUM        4       /* # array dimensions in auxiliary entry */
  398.  
  399. struct external_syment
  400. {
  401.   union {
  402.     char e_name[E_SYMNMLEN];
  403.     struct {
  404.       char e_zeroes[4];
  405.       char e_offset[4];
  406.     } e;
  407.   } e;
  408.   char e_value[4];
  409.   char e_scnum[2];
  410.   char e_type[2];
  411.   char e_sclass[1];
  412.   char e_numaux[1];
  413. };
  414.  
  415.  
  416. #define N_BTMASK        (017)
  417. #define N_TMASK         (060)
  418. #define N_BTSHFT        (4)
  419. #define N_TSHIFT        (2)
  420.  
  421.  
  422. union external_auxent {
  423.   struct {
  424.         char x_tagndx[4];       /* str, un, or enum tag indx */
  425.         union {
  426.           struct {
  427.                 char  x_lnno[2]; /* declaration line number */
  428.                 char  x_size[2]; /* str/union/array size */
  429.           } x_lnsz;
  430.           char x_fsize[4];      /* size of function */
  431.         } x_misc;
  432.         union {
  433.           struct {              /* if ISFCN, tag, or .bb */
  434.                 char x_lnnoptr[4];      /* ptr to fcn line # */
  435.                 char x_endndx[4];       /* entry ndx past block end */
  436.           } x_fcn;
  437.           struct {              /* if ISARY, up to 4 dimen. */
  438.                 char x_dimen[E_DIMNUM][2];
  439.           } x_ary;
  440.         } x_fcnary;
  441.         char x_tvndx[2];                /* tv index */
  442.   } x_sym;
  443.  
  444.   union {
  445.         char x_fname[E_FILNMLEN];
  446.         struct {
  447.           char x_zeroes[4];
  448.           char x_offset[4];
  449.         } x_n;
  450.   } x_file;
  451.  
  452.   struct {
  453.         char x_scnlen[4];                       /* section length */
  454.         char x_nreloc[2];       /* # relocation entries */
  455.         char x_nlinno[2];       /* # line numbers */
  456.   } x_scn;
  457.  
  458.   struct {
  459.         char x_tvfill[4];       /* tv fill value */
  460.         char x_tvlen[2];        /* length of .tv */
  461.         char x_tvran[2][2];     /* tv range */
  462.   } x_tv;               /* info about .tv section (in auxent of symbol .tv)) */
  463.  
  464.  
  465. };
  466.  
  467. #define SYMENT  struct external_syment
  468. #define SYMESZ  18     
  469. #define AUXENT  union external_auxent
  470. #define AUXESZ  18
  471.  
  472. /* section lengths are in target bytes (not host bytes) */
  473. #define GET_SCN_SCNLEN(ABFD, EXT) \
  474.   (H_GET_32 (ABFD, (EXT)->x_scn.x_scnlen) * bfd_octets_per_byte (ABFD))
  475. #define PUT_SCN_SCNLEN(ABFD, INT, EXT) \
  476.   H_PUT_32 (ABFD, (INT) / bfd_octets_per_byte (ABFD), (EXT)->x_scn.x_scnlen)
  477.  
  478. /* lnsz size is in bits in COFF file, in bytes in BFD */
  479. #define GET_LNSZ_SIZE(abfd, ext) \
  480.  (H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size) / (in_class != C_FIELD ? 8 : 1))
  481.  
  482. #define PUT_LNSZ_SIZE(abfd, in, ext) \
  483.   H_PUT_16 (abfd, ((in_class != C_FIELD) ? (in) * 8 : (in)), \
  484.            ext->x_sym.x_misc.x_lnsz.x_size)
  485.  
  486. /* TI COFF stores offsets for MOS and MOU in bits; BFD expects bytes
  487.    Also put the load page flag of the section into the symbol value if it's an
  488.    address.  */
  489. #ifndef NEEDS_PAGE
  490. #define NEEDS_PAGE(X) 0
  491. #define PAGE_MASK 0
  492. #endif
  493. #define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \
  494.   do                                                                    \
  495.     {                                                                   \
  496.       struct internal_syment *dst = (struct internal_syment *)(INT);    \
  497.       if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU)             \
  498.         dst->n_value /= 8;                                              \
  499.       else if (NEEDS_PAGE (dst->n_sclass)) {                            \
  500.         asection *scn = coff_section_from_bfd_index (abfd, dst->n_scnum); \
  501.         dst->n_value |= (scn->lma & PAGE_MASK);                         \
  502.       }                                                                 \
  503.     }                                                                   \
  504.    while (0)
  505.  
  506. #define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \
  507.   do                                                                    \
  508.     {                                                                   \
  509.        struct internal_syment *src = (struct internal_syment *)(INT);   \
  510.        SYMENT *dst = (SYMENT *)(EXT);                                   \
  511.        if (src->n_sclass == C_MOU || src->n_sclass == C_MOS)            \
  512.          H_PUT_32 (abfd, src->n_value * 8, dst->e_value);               \
  513.        else if (NEEDS_PAGE (src->n_sclass)) {                           \
  514.          H_PUT_32 (abfd, src->n_value &= ~PAGE_MASK, dst->e_value);     \
  515.        }                                                                \
  516.     }                                                                   \
  517.    while (0)
  518.  
  519. /* Detect section-relative absolute symbols so they get flagged with a sym
  520.    index of -1.
  521. */
  522. #define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC, SECT) \
  523.   ((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \
  524.    && (RELOC)->howto->name[0] == 'A')
  525.  
  526. /********************** RELOCATION DIRECTIVES **********************/
  527.  
  528. struct external_reloc_v0
  529. {
  530.   char r_vaddr[4];
  531.   char r_symndx[2];
  532.   char r_reserved[2];
  533.   char r_type[2];
  534. };
  535.  
  536. struct external_reloc
  537. {
  538.   char r_vaddr[4];
  539.   char r_symndx[4];
  540.   char r_reserved[2]; /* extended pmad byte for COFF2 */
  541.   char r_type[2];
  542. };
  543.  
  544. #define RELOC struct external_reloc
  545. #define RELSZ_V0 10                 /* FIXME -- coffcode.h needs fixing */
  546. #define RELSZ 12                    /* for COFF1/2 */
  547.  
  548. #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
  549.   do memset (dst->r_reserved, 0, sizeof (dst->r_reserved)); while (0)
  550.  
  551. /* various relocation types.  */
  552. #define R_ABS     0x0000            /* no relocation */
  553. #define R_REL13   0x002A            /* 13-bit direct reference (???) */
  554. #define R_PARTLS7 0x0028            /* 7 LSBs of an address */
  555. #define R_PARTMS9 0x0029            /* 9MSBs of an address */
  556. #define R_EXTWORD 0x002B            /* 23-bit direct reference */
  557. #define R_EXTWORD16 0x002C          /* 16-bit direct reference to 23-bit addr*/
  558. #define R_EXTWORDMS7 0x002D         /* upper 7 bits of 23-bit address */
  559.  
  560. #endif /* COFF_TI_H */
  561.