121308Sache/* COFF information for TI COFF support.  Definitions in this file should be
221308Sache   customized in a target-specific file, and then this file included (see
321308Sache   tic54x.h for an example).
421308Sache
5157184Sache   Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
621308Sache
721308Sache   This program is free software; you can redistribute it and/or modify
821308Sache   it under the terms of the GNU General Public License as published by
921308Sache   the Free Software Foundation; either version 2 of the License, or
1021308Sache   (at your option) any later version.
1121308Sache
1221308Sache   This program is distributed in the hope that it will be useful,
1358310Sache   but WITHOUT ANY WARRANTY; without even the implied warranty of
1421308Sache   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1521308Sache   GNU General Public License for more details.
1621308Sache
1721308Sache   You should have received a copy of the GNU General Public License
1821308Sache   along with this program; if not, write to the Free Software
1921308Sache   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2021308Sache#ifndef COFF_TI_H
2121308Sache#define COFF_TI_H
2221308Sache
2321308Sache/* Note "coff/external.h is not used because TI adds extra fields to the structures.  */
2458310Sache
2521308Sache/********************** FILE HEADER **********************/
2621308Sache
2721308Sachestruct external_filehdr
2821308Sache  {
2921308Sache    char f_magic[2];	/* magic number			*/
3021308Sache    char f_nscns[2];	/* number of sections		*/
3121308Sache    char f_timdat[4];	/* time & date stamp		*/
3221308Sache    char f_symptr[4];	/* file pointer to symtab	*/
3375406Sache    char f_nsyms[4];	/* number of symtab entries	*/
3475406Sache    char f_opthdr[2];	/* sizeof(optional hdr)		*/
3521308Sache    char f_flags[2];	/* flags			*/
3621308Sache    char f_target_id[2];    /* magic no. (TI COFF-specific) */
3721308Sache  };
3821308Sache
3921308Sache/* COFF0 has magic number in f_magic, and omits f_target_id from the file
4021308Sache   header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2
41157184Sache   and the target-specific magic number is found in f_target_id */
42157184Sache
43157184Sache#define TICOFF0MAGIC    TI_TARGET_ID
44157184Sache#define TICOFF1MAGIC    0x00C1
45157184Sache#define TICOFF2MAGIC    0x00C2
4621308Sache#define TICOFF_AOUT_MAGIC    0x0108 /* magic number in optional header */
4721308Sache#define TICOFF          1 /* customize coffcode.h */
4821308Sache
4921308Sache/* The target_id field changes depending on the particular CPU target */
5021308Sache/* for COFF0, the target id appeared in f_magic, where COFFX magic is now */
5121308Sache#ifndef TI_TARGET_ID
5221308Sache#error "TI_TARGET_ID needs to be defined for your CPU"
5321308Sache#endif
5421308Sache
5521308Sache/* Which bfd_arch to use... */
5621308Sache#ifndef TICOFF_TARGET_ARCH
5721308Sache#error "TICOFF_TARGET_ARCH needs to be defined for your CPU"
5821308Sache#endif
5921308Sache
6021308Sache#ifndef TICOFF_TARGET_MACHINE_GET
6121308Sache#define TICOFF_TARGET_MACHINE_GET(FLAGS) 0
6221308Sache#endif
6321308Sache
6421308Sache#ifndef TICOFF_TARGET_MACHINE_SET
6521308Sache#define TICOFF_TARGET_MACHINE_SET(FLAGSP, MACHINE)
6621308Sache#endif
6721308Sache
6821308Sache/* Default to COFF2 for file output */
6921308Sache#ifndef TICOFF_DEFAULT_MAGIC
7021308Sache#define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC
7121308Sache#endif
7221308Sache
7321308Sache/* This value is made available in the rare case where a bfd is unavailable */
7421308Sache#ifndef OCTETS_PER_BYTE_POWER
7521308Sache#error "OCTETS_PER_BYTE_POWER not defined for this CPU"
7621308Sache#else
7721308Sache#define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
7821308Sache#endif
7921308Sache
80119610Sache/* default alignment is on a byte (not octet!) boundary */
81119610Sache#ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER
8221308Sache#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
8321308Sache#endif
84136644Sache
85119610Sache/* TI COFF encodes the section alignment in the section header flags */
86119610Sache#define COFF_ALIGN_IN_SECTION_HEADER 1
87119610Sache#define COFF_ALIGN_IN_S_FLAGS 1
88119610Sache/* requires a power-of-two argument */
89119610Sache#define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8))
9021308Sache/* result is a power of two */
9121308Sache#define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF)
9221308Sache
9321308Sache#define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0)
9421308Sache#define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01)
9521308Sache
96119610Sache#define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC)
97119610Sache#define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID)
98119610Sache#define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID)
99119610Sache
100119610Sache/* we need to read/write an extra field in the coff file header */
101119610Sache#ifndef COFF_ADJUST_FILEHDR_IN_POST
102119610Sache#define COFF_ADJUST_FILEHDR_IN_POST(abfd, src, dst) \
10321308Sache  do									\
10421308Sache    {									\
10521308Sache      ((struct internal_filehdr *)(dst))->f_target_id =			\
10621308Sache	H_GET_16 (abfd, ((FILHDR *)(src))->f_target_id);		\
10721308Sache    }									\
10821308Sache  while (0)
10921308Sache#endif
11075406Sache
11121308Sache#ifndef COFF_ADJUST_FILEHDR_OUT_POST
11221308Sache#define COFF_ADJUST_FILEHDR_OUT_POST(abfd, src, dst) \
11375406Sache  do									\
11421308Sache    {									\
11521308Sache      H_PUT_16 (abfd, ((struct internal_filehdr *)(src))->f_target_id,	\
11621308Sache	       ((FILHDR *)(dst))->f_target_id);				\
117119610Sache    }									\
11821308Sache  while (0)
11921308Sache#endif
12021308Sache
12121308Sache#define	FILHDR	struct external_filehdr
12221308Sache#define	FILHSZ	22
12321308Sache#define FILHSZ_V0 20                /* COFF0 omits target_id field */
12421308Sache
12521308Sache/* File header flags */
12621308Sache#define	F_RELFLG	(0x0001)
12721308Sache#define	F_EXEC		(0x0002)
12821308Sache#define	F_LNNO		(0x0004)
12921308Sache#define F_VERS          (0x0010) /* TMS320C4x code */
13021308Sache/* F_LSYMS needs to be redefined in your source file */
13121308Sache#define	F_LSYMS_TICOFF	(0x0010) /* normal COFF is 0x8 */
13221308Sache
13321308Sache#define F_10            0x00    /* file built for TMS320C1x devices */
13421308Sache#define F_20            0x10    /* file built for TMS320C2x devices */
135119610Sache#define F_25            0x20    /* file built for TMS320C2x/C5x devices */
136119610Sache#define F_LENDIAN       0x0100  /* 16 bits/word, LSB first */
137119610Sache#define F_SYMMERGE      0x1000  /* duplicate symbols were removed */
138119610Sache
13921308Sache/********************** OPTIONAL HEADER **********************/
14021308Sache
14121308Sache
14221308Sachetypedef struct
14321308Sache{
14421308Sache  char 	magic[2];		/* type of file (0x108) 		*/
14558310Sache  char	vstamp[2];		/* version stamp			*/
14658310Sache  char	tsize[4];		/* text size in bytes, padded to FW bdry*/
14721308Sache  char	dsize[4];		/* initialized data "  "		*/
14821308Sache  char	bsize[4];		/* uninitialized data "   "		*/
14921308Sache  char	entry[4];		/* entry pt.				*/
15021308Sache  char 	text_start[4];		/* base of text used for this file */
15121308Sache  char 	data_start[4];		/* base of data used for this file */
15221308Sache}
153119610SacheAOUTHDR;
154119610Sache
155119610Sache
156119610Sache#define AOUTHDRSZ 28
15721308Sache#define AOUTSZ 28
15821308Sache
15921308Sache
16021308Sache/********************** SECTION HEADER **********************/
161/* COFF0, COFF1 */
162struct external_scnhdr_v01 {
163	char		s_name[8];	/* section name			*/
164	char		s_paddr[4];	/* physical address, aliased s_nlib */
165	char		s_vaddr[4];	/* virtual address		*/
166	char		s_size[4];	/* section size (in WORDS)      */
167	char		s_scnptr[4];	/* file ptr to raw data for section */
168	char		s_relptr[4];	/* file ptr to relocation	*/
169	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
170	char		s_nreloc[2];	/* number of relocation entries	*/
171	char		s_nlnno[2];	/* number of line number entries*/
172	char		s_flags[2];	/* flags			*/
173        char            s_reserved[1];  /* reserved                     */
174        char            s_page[1];      /* section page number (LOAD)   */
175};
176
177/* COFF2 */
178struct external_scnhdr {
179	char		s_name[8];	/* section name			*/
180	char		s_paddr[4];	/* physical address, aliased s_nlib */
181	char		s_vaddr[4];	/* virtual address		*/
182	char		s_size[4];	/* section size (in WORDS)      */
183	char		s_scnptr[4];	/* file ptr to raw data for section */
184	char		s_relptr[4];	/* file ptr to relocation	*/
185	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
186	char		s_nreloc[4];	/* number of relocation entries	*/
187	char		s_nlnno[4];	/* number of line number entries*/
188	char		s_flags[4];	/* flags			*/
189        char            s_reserved[2];  /* reserved                     */
190        char            s_page[2];      /* section page number (LOAD)   */
191};
192
193/*
194 * Special section flags
195 */
196
197/* TI COFF defines these flags;
198   STYP_CLINK: the section should be excluded from the final
199   linker output if there are no references found to any symbol in the section
200   STYP_BLOCK: the section should be blocked, i.e. if the section would cross
201   a page boundary, it is started at a page boundary instead.
202   TI COFF puts the section alignment power of two in the section flags
203   e.g. 2**N is alignment, flags |= (N & 0xF) << 8
204*/
205#define STYP_CLINK      (0x4000)
206#define STYP_BLOCK      (0x1000)
207#define STYP_ALIGN      (0x0F00) /* TI COFF stores section alignment here */
208
209#define	SCNHDR_V01 struct external_scnhdr_v01
210#define SCNHDR struct external_scnhdr
211#define	SCNHSZ_V01 40                  /* for v0 and v1 */
212#define SCNHSZ 48
213
214/* COFF2 changes the offsets and sizes of these fields
215   Assume we're dealing with the COFF2 scnhdr structure, and adjust
216   accordingly
217 */
218#define GET_SCNHDR_NRELOC(ABFD, LOC) \
219  (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, LOC))
220#define PUT_SCNHDR_NRELOC(ABFD, VAL, LOC) \
221  (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, LOC))
222#define GET_SCNHDR_NLNNO(ABFD, LOC) \
223  (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 2))
224#define PUT_SCNHDR_NLNNO(ABFD, VAL, LOC) \
225  (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 2))
226#define GET_SCNHDR_FLAGS(ABFD, LOC) \
227  (COFF2_P (ABFD) ? H_GET_32 (ABFD, LOC) : H_GET_16 (ABFD, (LOC) - 4))
228#define PUT_SCNHDR_FLAGS(ABFD, VAL, LOC) \
229  (COFF2_P (ABFD) ? H_PUT_32 (ABFD, VAL, LOC) : H_PUT_16 (ABFD, VAL, (LOC) - 4))
230#define GET_SCNHDR_PAGE(ABFD, LOC) \
231  (COFF2_P (ABFD) ? H_GET_16 (ABFD, LOC) : (unsigned) H_GET_8 (ABFD, (LOC) - 7))
232/* on output, make sure that the "reserved" field is zero */
233#define PUT_SCNHDR_PAGE(ABFD, VAL, LOC) \
234  (COFF2_P (ABFD) \
235   ? H_PUT_16 (ABFD, VAL, LOC) \
236   : H_PUT_8 (ABFD, VAL, (LOC) - 7), H_PUT_8 (ABFD, 0, (LOC) - 8))
237
238/* TI COFF stores section size as number of bytes (address units, not octets),
239   so adjust to be number of octets, which is what BFD expects */
240#define GET_SCNHDR_SIZE(ABFD, SZP) \
241  (H_GET_32 (ABFD, SZP) * bfd_octets_per_byte (ABFD))
242#define PUT_SCNHDR_SIZE(ABFD, SZ, SZP) \
243  H_PUT_32 (ABFD, (SZ) / bfd_octets_per_byte (ABFD), SZP)
244
245#define COFF_ADJUST_SCNHDR_IN_POST(ABFD, EXT, INT) \
246  do									\
247    {									\
248      ((struct internal_scnhdr *)(INT))->s_page =			\
249	GET_SCNHDR_PAGE (ABFD, ((SCNHDR *)(EXT))->s_page);		\
250    }									\
251   while (0)
252
253/* The line number and reloc overflow checking in coff_swap_scnhdr_out in
254   coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc.
255   Due to different sized v0/v1/v2 section headers, we have to re-write these
256   fields.
257 */
258#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD, INT, EXT) \
259  do									   \
260    {									   \
261      PUT_SCNHDR_NLNNO (ABFD, ((struct internal_scnhdr *)(INT))->s_nlnno,  \
262			((SCNHDR *)(EXT))->s_nlnno);			   \
263      PUT_SCNHDR_NRELOC (ABFD, ((struct internal_scnhdr *)(INT))->s_nreloc,\
264			 ((SCNHDR *)(EXT))->s_nreloc);			   \
265      PUT_SCNHDR_FLAGS (ABFD, ((struct internal_scnhdr *)(INT))->s_flags,  \
266			((SCNHDR *)(EXT))->s_flags);			   \
267      PUT_SCNHDR_PAGE (ABFD, ((struct internal_scnhdr *)(INT))->s_page,    \
268		       ((SCNHDR *)(EXT))->s_page);			   \
269    }									   \
270   while (0)
271
272/*
273 * names of "special" sections
274 */
275#define _TEXT	".text"
276#define _DATA	".data"
277#define _BSS	".bss"
278#define _CINIT  ".cinit"            /* initialized C data */
279#define _SCONST  ".const"           /* constants */
280#define _SWITCH ".switch"           /* switch tables */
281#define _STACK  ".stack"            /* C stack */
282#define _SYSMEM ".sysmem"           /* used for malloc et al. syscalls */
283
284/********************** LINE NUMBERS **********************/
285
286/* 1 line number entry for every "breakpointable" source line in a section.
287 * Line numbers are grouped on a per function basis; first entry in a function
288 * grouping will have l_lnno = 0 and in place of physical address will be the
289 * symbol table index of the function name.
290 */
291struct external_lineno {
292  union {
293    char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
294    char l_paddr[4];	/* (physical) address of line number	*/
295  } l_addr;
296  char l_lnno[2];	/* line number		*/
297};
298
299#define	LINENO	struct external_lineno
300#define	LINESZ	6
301
302
303/********************** SYMBOLS **********************/
304
305/* NOTE: this is what a local label looks like in assembly source; what it
306   looks like in COFF output is undefined */
307#define TICOFF_LOCAL_LABEL_P(NAME) \
308((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \
309 || NAME[strlen(NAME)-1] == '?')
310
311#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
312#define E_FILNMLEN	14	/* # characters in a file name		*/
313#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
314
315struct external_syment
316{
317  union {
318    char e_name[E_SYMNMLEN];
319    struct {
320      char e_zeroes[4];
321      char e_offset[4];
322    } e;
323  } e;
324  char e_value[4];
325  char e_scnum[2];
326  char e_type[2];
327  char e_sclass[1];
328  char e_numaux[1];
329};
330
331
332#define N_BTMASK	(017)
333#define N_TMASK		(060)
334#define N_BTSHFT	(4)
335#define N_TSHIFT	(2)
336
337
338union external_auxent {
339  struct {
340	char x_tagndx[4];	/* str, un, or enum tag indx */
341	union {
342	  struct {
343		char  x_lnno[2]; /* declaration line number */
344		char  x_size[2]; /* str/union/array size */
345	  } x_lnsz;
346	  char x_fsize[4];	/* size of function */
347	} x_misc;
348	union {
349	  struct {		/* if ISFCN, tag, or .bb */
350		char x_lnnoptr[4];	/* ptr to fcn line # */
351		char x_endndx[4];	/* entry ndx past block end */
352	  } x_fcn;
353	  struct {		/* if ISARY, up to 4 dimen. */
354		char x_dimen[E_DIMNUM][2];
355	  } x_ary;
356	} x_fcnary;
357	char x_tvndx[2];		/* tv index */
358  } x_sym;
359
360  union {
361	char x_fname[E_FILNMLEN];
362	struct {
363	  char x_zeroes[4];
364	  char x_offset[4];
365	} x_n;
366  } x_file;
367
368  struct {
369	char x_scnlen[4];			/* section length */
370	char x_nreloc[2];	/* # relocation entries */
371	char x_nlinno[2];	/* # line numbers */
372  } x_scn;
373
374  struct {
375	char x_tvfill[4];	/* tv fill value */
376	char x_tvlen[2];	/* length of .tv */
377	char x_tvran[2][2];	/* tv range */
378  } x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
379
380
381};
382
383#define	SYMENT	struct external_syment
384#define	SYMESZ	18
385#define	AUXENT	union external_auxent
386#define	AUXESZ	18
387
388/* section lengths are in target bytes (not host bytes) */
389#define GET_SCN_SCNLEN(ABFD, EXT) \
390  (H_GET_32 (ABFD, (EXT)->x_scn.x_scnlen) * bfd_octets_per_byte (ABFD))
391#define PUT_SCN_SCNLEN(ABFD, INT, EXT) \
392  H_PUT_32 (ABFD, (INT) / bfd_octets_per_byte (ABFD), (EXT)->x_scn.x_scnlen)
393
394/* lnsz size is in bits in COFF file, in bytes in BFD */
395#define GET_LNSZ_SIZE(abfd, ext) \
396 (H_GET_16 (abfd, ext->x_sym.x_misc.x_lnsz.x_size) / (class != C_FIELD ? 8 : 1))
397
398#define PUT_LNSZ_SIZE(abfd, in, ext) \
399  H_PUT_16 (abfd, ((class != C_FIELD) ? (in) * 8 : (in)), \
400	   ext->x_sym.x_misc.x_lnsz.x_size)
401
402/* TI COFF stores offsets for MOS and MOU in bits; BFD expects bytes
403   Also put the load page flag of the section into the symbol value if it's an
404   address.  */
405#ifndef NEEDS_PAGE
406#define NEEDS_PAGE(X) 0
407#define PAGE_MASK 0
408#endif
409#define COFF_ADJUST_SYM_IN_POST(ABFD, EXT, INT) \
410  do									\
411    {									\
412      struct internal_syment *dst = (struct internal_syment *)(INT);	\
413      if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU)		\
414	dst->n_value /= 8;						\
415      else if (NEEDS_PAGE (dst->n_sclass)) {                            \
416        asection *scn = coff_section_from_bfd_index (abfd, dst->n_scnum); \
417        dst->n_value |= (scn->lma & PAGE_MASK);                         \
418      }									\
419    }									\
420   while (0)
421
422#define COFF_ADJUST_SYM_OUT_POST(ABFD, INT, EXT) \
423  do									\
424    {									\
425       struct internal_syment *src = (struct internal_syment *)(INT);	\
426       SYMENT *dst = (SYMENT *)(EXT);					\
427       if (src->n_sclass == C_MOU || src->n_sclass == C_MOS)		\
428	 H_PUT_32 (abfd, src->n_value * 8, dst->e_value);		\
429       else if (NEEDS_PAGE (src->n_sclass)) {                           \
430         H_PUT_32 (abfd, src->n_value &= ~PAGE_MASK, dst->e_value);     \
431       }								\
432    }									\
433   while (0)
434
435/* Detect section-relative absolute symbols so they get flagged with a sym
436   index of -1.
437*/
438#define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC, SECT) \
439  ((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \
440   && (RELOC)->howto->name[0] == 'A')
441
442/********************** RELOCATION DIRECTIVES **********************/
443
444struct external_reloc_v0
445{
446  char r_vaddr[4];
447  char r_symndx[2];
448  char r_reserved[2];
449  char r_type[2];
450};
451
452struct external_reloc
453{
454  char r_vaddr[4];
455  char r_symndx[4];
456  char r_reserved[2]; /* extended pmad byte for COFF2 */
457  char r_type[2];
458};
459
460#define RELOC struct external_reloc
461#define RELSZ_V0 10                 /* FIXME -- coffcode.h needs fixing */
462#define RELSZ 12                    /* for COFF1/2 */
463
464/* various relocation types.  */
465#define R_ABS     0x0000            /* no relocation */
466#define R_REL13   0x002A            /* 13-bit direct reference (???) */
467#define R_PARTLS7 0x0028            /* 7 LSBs of an address */
468#define R_PARTMS9 0x0029            /* 9MSBs of an address */
469#define R_EXTWORD 0x002B            /* 23-bit direct reference */
470#define R_EXTWORD16 0x002C          /* 16-bit direct reference to 23-bit addr*/
471#define R_EXTWORDMS7 0x002D         /* upper 7 bits of 23-bit address */
472
473#endif /* COFF_TI_H */
474