ti.h revision 77298
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#ifndef COFF_TI_H
5#define COFF_TI_H
6
7/********************** FILE HEADER **********************/
8
9struct external_filehdr {
10	char f_magic[2];	/* magic number			*/
11	char f_nscns[2];	/* number of sections		*/
12	char f_timdat[4];	/* time & date stamp		*/
13	char f_symptr[4];	/* file pointer to symtab	*/
14	char f_nsyms[4];	/* number of symtab entries	*/
15	char f_opthdr[2];	/* sizeof(optional hdr)		*/
16	char f_flags[2];	/* flags			*/
17        char f_target_id[2];    /* magic no. (TI COFF-specific) */
18};
19
20/* COFF0 has magic number in f_magic, and omits f_target_id from the file
21   header; for later versions, f_magic is 0xC1 for COFF1 and 0xC2 for COFF2
22   and the target-specific magic number is found in f_target_id */
23
24#define TICOFF0MAGIC    TI_TARGET_ID
25#define TICOFF1MAGIC    0x00C1
26#define TICOFF2MAGIC    0x00C2
27#define TICOFF_AOUT_MAGIC    0x0108 /* magic number in optional header */
28#define TICOFF          1 /* customize coffcode.h */
29
30/* The target_id field changes depending on the particular CPU target */
31/* for COFF0, the target id appeared in f_magic, where COFFX magic is now */
32#ifndef TI_TARGET_ID
33#error "TI_TARGET_ID needs to be defined for your CPU"
34#endif
35
36/* Which bfd_arch to use... */
37#ifndef TICOFF_TARGET_ARCH
38#error "TICOFF_TARGET_ARCH needs to be defined for your CPU"
39#endif
40
41/* Default to COFF2 for file output */
42#ifndef TICOFF_DEFAULT_MAGIC
43#define TICOFF_DEFAULT_MAGIC TICOFF2MAGIC
44#endif
45
46/* This value is made available in the rare case where a bfd is unavailable */
47#ifndef OCTETS_PER_BYTE_POWER
48#error "OCTETS_PER_BYTE_POWER not defined for this CPU"
49#else
50#define OCTETS_PER_BYTE (1<<OCTETS_PER_BYTE_POWER)
51#endif
52
53/* default alignment is on a byte (not octet!) boundary */
54#ifndef COFF_DEFAULT_SECTION_ALIGNMENT_POWER
55#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 0
56#endif
57
58/* TI COFF encodes the section alignment in the section header flags */
59#define COFF_ALIGN_IN_SECTION_HEADER 1
60#define COFF_ALIGN_IN_S_FLAGS 1
61/* requires a power-of-two argument */
62#define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X)&0xF)<<8))
63/* result is a power of two */
64#define COFF_DECODE_ALIGNMENT(X) (((X)>>8)&0xF)
65
66#define COFF0_P(ABFD) (bfd_coff_filhsz(ABFD) == FILHSZ_V0)
67#define COFF2_P(ABFD) (bfd_coff_scnhsz(ABFD) != SCNHSZ_V01)
68
69#define COFF0_BADMAG(x) ((x).f_magic != TICOFF0MAGIC)
70#define COFF1_BADMAG(x) ((x).f_magic != TICOFF1MAGIC || (x).f_target_id != TI_TARGET_ID)
71#define COFF2_BADMAG(x) ((x).f_magic != TICOFF2MAGIC || (x).f_target_id != TI_TARGET_ID)
72
73/* we need to read/write an extra field in the coff file header */
74#ifndef COFF_ADJUST_FILEHDR_IN_POST
75#define COFF_ADJUST_FILEHDR_IN_POST(abfd,src,dst) \
76do { ((struct internal_filehdr *)(dst))->f_target_id = \
77bfd_h_get_16(abfd, (bfd_byte *)(((FILHDR *)(src))->f_target_id)); \
78} while(0)
79#endif
80
81#ifndef COFF_ADJUST_FILEHDR_OUT_POST
82#define COFF_ADJUST_FILEHDR_OUT_POST(abfd,src,dst) \
83do { bfd_h_put_16(abfd, ((struct internal_filehdr *)(src))->f_target_id, \
84             (bfd_byte *)(((FILHDR *)(dst))->f_target_id)); \
85} while(0)
86#endif
87
88#define	FILHDR	struct external_filehdr
89#define	FILHSZ	22
90#define FILHSZ_V0 20                /* COFF0 omits target_id field */
91
92/* File header flags */
93#define	F_RELFLG	(0x0001)
94#define	F_EXEC		(0x0002)
95#define	F_LNNO		(0x0004)
96/* F_LSYMS needs to be redefined in your source file */
97#define	F_LSYMS_TICOFF	(0x0010) /* normal COFF is 0x8 */
98
99#define F_10            0x00    /* file built for TMS320C1x devices */
100#define F_20            0x10    /* file built for TMS320C2x devices */
101#define F_25            0x20    /* file built for TMS320C2x/C5x devices */
102#define F_LENDIAN       0x0100  /* 16 bits/word, LSB first */
103#define F_SYMMERGE      0x1000  /* duplicate symbols were removed */
104
105/********************** OPTIONAL HEADER **********************/
106
107
108typedef struct
109{
110  char 	magic[2];		/* type of file (0x108) 		*/
111  char	vstamp[2];		/* version stamp			*/
112  char	tsize[4];		/* text size in bytes, padded to FW bdry*/
113  char	dsize[4];		/* initialized data "  "		*/
114  char	bsize[4];		/* uninitialized data "   "		*/
115  char	entry[4];		/* entry pt.				*/
116  char 	text_start[4];		/* base of text used for this file */
117  char 	data_start[4];		/* base of data used for this file */
118}
119AOUTHDR;
120
121
122#define AOUTHDRSZ 28
123#define AOUTSZ 28
124
125
126/********************** SECTION HEADER **********************/
127/* COFF0, COFF1 */
128struct external_scnhdr_v01 {
129	char		s_name[8];	/* section name			*/
130	char		s_paddr[4];	/* physical address, aliased s_nlib */
131	char		s_vaddr[4];	/* virtual address		*/
132	char		s_size[4];	/* section size (in WORDS)      */
133	char		s_scnptr[4];	/* file ptr to raw data for section */
134	char		s_relptr[4];	/* file ptr to relocation	*/
135	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
136	char		s_nreloc[2];	/* number of relocation entries	*/
137	char		s_nlnno[2];	/* number of line number entries*/
138	char		s_flags[2];	/* flags			*/
139        char            s_reserved[1];  /* reserved                     */
140        char            s_page[1];      /* section page number (LOAD)   */
141};
142
143/* COFF2 */
144struct external_scnhdr {
145	char		s_name[8];	/* section name			*/
146	char		s_paddr[4];	/* physical address, aliased s_nlib */
147	char		s_vaddr[4];	/* virtual address		*/
148	char		s_size[4];	/* section size (in WORDS)      */
149	char		s_scnptr[4];	/* file ptr to raw data for section */
150	char		s_relptr[4];	/* file ptr to relocation	*/
151	char		s_lnnoptr[4];	/* file ptr to line numbers	*/
152	char		s_nreloc[4];	/* number of relocation entries	*/
153	char		s_nlnno[4];	/* number of line number entries*/
154	char		s_flags[4];	/* flags			*/
155        char            s_reserved[2];  /* reserved                     */
156        char            s_page[2];      /* section page number (LOAD)   */
157};
158
159/*
160 * Special section flags
161 */
162
163/* TI COFF defines these flags;
164   STYP_CLINK: the section should be excluded from the final
165   linker output if there are no references found to any symbol in the section
166   STYP_BLOCK: the section should be blocked, i.e. if the section would cross
167   a page boundary, it is started at a page boundary instead.
168   TI COFF puts the section alignment power of two in the section flags
169   e.g. 2**N is alignment, flags |= (N & 0xF) << 8
170*/
171#define STYP_CLINK      (0x4000)
172#define STYP_BLOCK      (0x1000)
173#define STYP_ALIGN      (0x0F00) /* TI COFF stores section alignment here */
174
175#define	SCNHDR_V01 struct external_scnhdr_v01
176#define SCNHDR struct external_scnhdr
177#define	SCNHSZ_V01 40                  /* for v0 and v1 */
178#define SCNHSZ 48
179
180/* COFF2 changes the offsets and sizes of these fields
181   Assume we're dealing with the COFF2 scnhdr structure, and adjust
182   accordingly
183 */
184#define GET_SCNHDR_NRELOC(ABFD,PTR) \
185(COFF2_P(ABFD) ? bfd_h_get_32 (ABFD,PTR) : bfd_h_get_16 (ABFD, PTR))
186#define PUT_SCNHDR_NRELOC(ABFD,VAL,PTR) \
187(COFF2_P(ABFD) ? bfd_h_put_32 (ABFD,VAL,PTR) : bfd_h_put_16 (ABFD,VAL,PTR))
188#define GET_SCNHDR_NLNNO(ABFD,PTR) \
189(COFF2_P(ABFD) ? bfd_h_get_32 (ABFD,PTR) : bfd_h_get_16 (ABFD, (PTR)-2))
190#define PUT_SCNHDR_NLNNO(ABFD,VAL,PTR) \
191(COFF2_P(ABFD) ? bfd_h_put_32 (ABFD,VAL,PTR) : bfd_h_put_16 (ABFD,VAL,(PTR)-2))
192#define GET_SCNHDR_FLAGS(ABFD,PTR) \
193(COFF2_P(ABFD) ? bfd_h_get_32 (ABFD,PTR) : bfd_h_get_16 (ABFD, (PTR)-4))
194#define PUT_SCNHDR_FLAGS(ABFD,VAL,PTR) \
195(COFF2_P(ABFD) ? bfd_h_put_32 (ABFD,VAL,PTR) : bfd_h_put_16 (ABFD,VAL,(PTR)-4))
196#define GET_SCNHDR_PAGE(ABFD,PTR) \
197(COFF2_P(ABFD) ? bfd_h_get_16 (ABFD,PTR) : bfd_h_get_8 (ABFD, (PTR)-7))
198/* on output, make sure that the "reserved" field is zero */
199#define PUT_SCNHDR_PAGE(ABFD,VAL,PTR) \
200(COFF2_P(ABFD) ? bfd_h_put_16 (ABFD,VAL,PTR) : \
201bfd_h_put_8 (ABFD,VAL,(PTR)-7), bfd_h_put_8 (ABFD, 0, (PTR)-8))
202
203/* TI COFF stores section size as number of bytes (address units, not octets),
204   so adjust to be number of octets, which is what BFD expects */
205#define GET_SCNHDR_SIZE(ABFD,SZP) \
206(bfd_h_get_32(ABFD,SZP)*bfd_octets_per_byte(ABFD))
207#define PUT_SCNHDR_SIZE(ABFD,SZ,SZP) \
208bfd_h_put_32(ABFD,(SZ)/bfd_octets_per_byte(ABFD),SZP)
209
210#define COFF_ADJUST_SCNHDR_IN_POST(ABFD,EXT,INT) \
211do { ((struct internal_scnhdr *)(INT))->s_page = \
212GET_SCNHDR_PAGE(ABFD,(bfd_byte *)((SCNHDR *)(EXT))->s_page); \
213} while(0)
214
215/* The line number and reloc overflow checking in coff_swap_scnhdr_out in
216   coffswap.h doesn't use PUT_X for s_nlnno and s_nreloc.
217   Due to different sized v0/v1/v2 section headers, we have to re-write these
218   fields.
219 */
220#define COFF_ADJUST_SCNHDR_OUT_POST(ABFD,INT,EXT) \
221do { \
222PUT_SCNHDR_NLNNO(ABFD,((struct internal_scnhdr *)(INT))->s_nlnno,\
223                (bfd_byte *)((SCNHDR *)(EXT))->s_nlnno); \
224PUT_SCNHDR_NRELOC(ABFD,((struct internal_scnhdr *)(INT))->s_nreloc,\
225                (bfd_byte *)((SCNHDR *)(EXT))->s_nreloc); \
226PUT_SCNHDR_FLAGS(ABFD,((struct internal_scnhdr *)(INT))->s_flags, \
227                (bfd_byte *)((SCNHDR *)(EXT))->s_flags); \
228PUT_SCNHDR_PAGE(ABFD,((struct internal_scnhdr *)(INT))->s_page, \
229                (bfd_byte *)((SCNHDR *)(EXT))->s_page); \
230} while(0)
231
232/* Page macros
233
234   The first GDB port requires flags in its remote memory access commands to
235   distinguish between data/prog space.  Hopefully we can make this go away
236   eventually.  Stuff the page in the upper bits of a 32-bit address, since
237   the c5x family only uses 16 or 23 bits.
238
239   c2x, c5x and most c54x devices have 16-bit addresses, but the c548 has
240   23-bit program addresses.  Make sure the page flags don't interfere.
241   These flags are used by GDB to identify the destination page for
242   addresses.
243*/
244
245/* recognized load pages */
246#define PG_PROG         0x0         /* PROG page */
247#define PG_DATA         0x1         /* DATA page */
248
249#define ADDR_MASK       0x00FFFFFF
250#define PG_TO_FLAG(p)   (((unsigned long)(p) & 0xFF) << 24)
251#define FLAG_TO_PG(f)   (((f) >> 24) & 0xFF)
252
253/*
254 * names of "special" sections
255 */
256#define _TEXT	".text"
257#define _DATA	".data"
258#define _BSS	".bss"
259#define _CINIT  ".cinit"            /* initialized C data */
260#define _SCONST  ".const"           /* constants */
261#define _SWITCH ".switch"           /* switch tables */
262#define _STACK  ".stack"            /* C stack */
263#define _SYSMEM ".sysmem"           /* used for malloc et al. syscalls */
264
265/********************** LINE NUMBERS **********************/
266
267/* 1 line number entry for every "breakpointable" source line in a section.
268 * Line numbers are grouped on a per function basis; first entry in a function
269 * grouping will have l_lnno = 0 and in place of physical address will be the
270 * symbol table index of the function name.
271 */
272struct external_lineno {
273  union {
274    char l_symndx[4];	/* function name symbol index, iff l_lnno == 0*/
275    char l_paddr[4];	/* (physical) address of line number	*/
276  } l_addr;
277  char l_lnno[2];	/* line number		*/
278};
279
280#define	LINENO	struct external_lineno
281#define	LINESZ	6
282
283
284/********************** SYMBOLS **********************/
285
286/* NOTE: this is what a local label looks like in assembly source; what it
287   looks like in COFF output is undefined */
288#define TICOFF_LOCAL_LABEL_P(NAME) \
289((NAME[0] == '$' && NAME[1] >= '0' && NAME[1] <= '9' && NAME[2] == '\0') \
290 || NAME[strlen(NAME)-1] == '?')
291
292#define E_SYMNMLEN	8	/* # characters in a symbol name	*/
293#define E_FILNMLEN	14	/* # characters in a file name		*/
294#define E_DIMNUM	4	/* # array dimensions in auxiliary entry */
295
296struct external_syment
297{
298  union {
299    char e_name[E_SYMNMLEN];
300    struct {
301      char e_zeroes[4];
302      char e_offset[4];
303    } e;
304  } e;
305  char e_value[4];
306  char e_scnum[2];
307  char e_type[2];
308  char e_sclass[1];
309  char e_numaux[1];
310};
311
312
313#define N_BTMASK	(017)
314#define N_TMASK		(060)
315#define N_BTSHFT	(4)
316#define N_TSHIFT	(2)
317
318
319union external_auxent {
320  struct {
321	char x_tagndx[4];	/* str, un, or enum tag indx */
322	union {
323	  struct {
324		char  x_lnno[2]; /* declaration line number */
325		char  x_size[2]; /* str/union/array size */
326	  } x_lnsz;
327	  char x_fsize[4];	/* size of function */
328	} x_misc;
329	union {
330	  struct {		/* if ISFCN, tag, or .bb */
331		char x_lnnoptr[4];	/* ptr to fcn line # */
332		char x_endndx[4];	/* entry ndx past block end */
333	  } x_fcn;
334	  struct {		/* if ISARY, up to 4 dimen. */
335		char x_dimen[E_DIMNUM][2];
336	  } x_ary;
337	} x_fcnary;
338	char x_tvndx[2];		/* tv index */
339  } x_sym;
340
341  union {
342	char x_fname[E_FILNMLEN];
343	struct {
344	  char x_zeroes[4];
345	  char x_offset[4];
346	} x_n;
347  } x_file;
348
349  struct {
350	char x_scnlen[4];			/* section length */
351	char x_nreloc[2];	/* # relocation entries */
352	char x_nlinno[2];	/* # line numbers */
353  } x_scn;
354
355  struct {
356	char x_tvfill[4];	/* tv fill value */
357	char x_tvlen[2];	/* length of .tv */
358	char x_tvran[2][2];	/* tv range */
359  } x_tv;		/* info about .tv section (in auxent of symbol .tv)) */
360
361
362};
363
364#define	SYMENT	struct external_syment
365#define	SYMESZ	18
366#define	AUXENT	union external_auxent
367#define	AUXESZ	18
368
369/* section lengths are in target bytes (not host bytes) */
370#define GET_SCN_SCNLEN(ABFD,EXT) \
371(bfd_h_get_32(ABFD,(bfd_byte *)(EXT)->x_scn.x_scnlen)*bfd_octets_per_byte(ABFD))
372#define PUT_SCN_SCNLEN(ABFD,INT,EXT) \
373bfd_h_put_32(ABFD,(INT)/bfd_octets_per_byte(ABFD),\
374             (bfd_byte *)(EXT)->x_scn.x_scnlen)
375
376/* lnsz size is in bits in COFF file, in bytes in BFD */
377#define GET_LNSZ_SIZE(abfd, ext) \
378(bfd_h_get_16(abfd, (bfd_byte *)ext->x_sym.x_misc.x_lnsz.x_size) / \
379 (class != C_FIELD ? 8 : 1))
380
381#define PUT_LNSZ_SIZE(abfd, in, ext) \
382 bfd_h_put_16(abfd, ((class != C_FIELD) ? (in)*8 : (in)), \
383              (bfd_byte*) ext->x_sym.x_misc.x_lnsz.x_size)
384
385/* TI COFF stores offsets for MOS and MOU in bits; BFD expects bytes */
386#define COFF_ADJUST_SYM_IN_POST(ABFD,EXT,INT) \
387do { struct internal_syment *dst = (struct internal_syment *)(INT); \
388if (dst->n_sclass == C_MOS || dst->n_sclass == C_MOU) dst->n_value /= 8; \
389} while (0)
390
391#define COFF_ADJUST_SYM_OUT_POST(ABFD,INT,EXT) \
392do { struct internal_syment *src = (struct internal_syment *)(INT); \
393SYMENT *dst = (SYMENT *)(EXT); \
394if(src->n_sclass == C_MOU || src->n_sclass == C_MOS) \
395bfd_h_put_32(abfd,src->n_value * 8,(bfd_byte *)dst->e_value); \
396} while (0)
397
398/* Detect section-relative absolute symbols so they get flagged with a sym
399   index of -1.
400*/
401#define SECTION_RELATIVE_ABSOLUTE_SYMBOL_P(RELOC,SECT) \
402((*(RELOC)->sym_ptr_ptr)->section->output_section == (SECT) \
403 && (RELOC)->howto->name[0] == 'A')
404
405/********************** RELOCATION DIRECTIVES **********************/
406
407struct external_reloc_v0 {
408  char r_vaddr[4];
409  char r_symndx[2];
410  char r_reserved[2];
411  char r_type[2];
412};
413
414struct external_reloc {
415  char r_vaddr[4];
416  char r_symndx[4];
417  char r_reserved[2]; /* extended pmad byte for COFF2 */
418  char r_type[2];
419};
420
421#define RELOC struct external_reloc
422#define RELSZ_V0 10                 /* FIXME -- coffcode.h needs fixing */
423#define RELSZ 12                    /* for COFF1/2 */
424
425/* various relocation types.  */
426#define R_ABS     0x0000            /* no relocation */
427#define R_REL13   0x002A            /* 13-bit direct reference (???) */
428#define R_PARTLS7 0x0028            /* 7 LSBs of an address */
429#define R_PARTMS9 0x0029            /* 9MSBs of an address */
430#define R_EXTWORD 0x002B            /* 23-bit direct reference */
431#define R_EXTWORD16 0x002C          /* 16-bit direct reference to 23-bit addr*/
432#define R_EXTWORDMS7 0x002D         /* upper 7 bits of 23-bit address */
433
434#endif /* COFF_TI_H */
435