* Makefile.in (tmp-ld-decode): Fix dependencies.
[deliverable/binutils-gdb.git] / gas / config / tc-xc16x.c
1 /* tc-xc16x.c -- Assembler for the Infineon XC16X.
2 Copyright 2006 Free Software Foundation, Inc.
3 Contributed by KPIT Cummins Infosystems
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS 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 2, or (at your option)
10 any later version.
11
12 GAS 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 GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
22
23 #include <stdio.h>
24 #include "as.h"
25 #include "safe-ctype.h"
26 #include "subsegs.h"
27 #include "symcat.h"
28 #include "opcodes/xc16x-desc.h"
29 #include "opcodes/xc16x-opc.h"
30 #include "cgen.h"
31 #include "bfd.h"
32 #include "dwarf2dbg.h"
33
34
35 #ifdef OBJ_ELF
36 #include "elf/xc16x.h"
37 #endif
38
39 /* Structure to hold all of the different components describing
40 an individual instruction. */
41 typedef struct
42 {
43 const CGEN_INSN * insn;
44 const CGEN_INSN * orig_insn;
45 CGEN_FIELDS fields;
46 #if CGEN_INT_INSN_P
47 CGEN_INSN_INT buffer [1];
48 #define INSN_VALUE(buf) (*(buf))
49 #else
50 unsigned char buffer [CGEN_MAX_INSN_SIZE];
51 #define INSN_VALUE(buf) (buf)
52 #endif
53 char * addr;
54 fragS * frag;
55 int num_fixups;
56 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
57 int indices [MAX_OPERAND_INSTANCES];
58 }
59 xc16x_insn;
60
61 const char comment_chars[] = ";";
62 const char line_comment_chars[] = "#";
63 const char line_separator_chars[] = "";
64 const char EXP_CHARS[] = "eE";
65 const char FLT_CHARS[] = "dD";
66
67 #define XC16X_SHORTOPTS ""
68 const char * md_shortopts = XC16X_SHORTOPTS;
69
70 struct option md_longopts[] =
71 {
72 {NULL, no_argument, NULL, 0}
73 };
74 size_t md_longopts_size = sizeof (md_longopts);
75
76 static void
77 xc16xlmode (int arg ATTRIBUTE_UNUSED)
78 {
79 if (stdoutput != NULL)
80 if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16xl))
81 as_warn (_("could not set architecture and machine"));
82 }
83
84 static void
85 xc16xsmode (int arg ATTRIBUTE_UNUSED)
86 {
87 if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16xs))
88 as_warn (_("could not set architecture and machine"));
89 }
90
91 static void
92 xc16xmode (int arg ATTRIBUTE_UNUSED)
93 {
94 if (!bfd_set_arch_mach (stdoutput, bfd_arch_xc16x, bfd_mach_xc16x))
95 as_warn (_("could not set architecture and machine"));
96 }
97
98 /* The target specific pseudo-ops which we support. */
99 const pseudo_typeS md_pseudo_table[] =
100 {
101 { "word", cons, 2 },
102 {"xc16xl", xc16xlmode, 0},
103 {"xc16xs", xc16xsmode, 0},
104 {"xc16x", xc16xmode, 0},
105 { NULL, NULL, 0 }
106 };
107
108 void
109 md_begin (void)
110 {
111 /* Initialize the `cgen' interface. */
112
113 /* Set the machine number and endian. */
114 gas_cgen_cpu_desc = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
115 CGEN_CPU_OPEN_ENDIAN,
116 CGEN_ENDIAN_LITTLE,
117 CGEN_CPU_OPEN_END);
118 xc16x_cgen_init_asm (gas_cgen_cpu_desc);
119
120 /* This is a callback from cgen to gas to parse operands. */
121 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
122 }
123
124 void
125 md_assemble (char *str)
126 {
127 xc16x_insn insn;
128 char *errmsg;
129
130 /* Initialize GAS's cgen interface for a new instruction. */
131 gas_cgen_init_parse ();
132
133 insn.insn = xc16x_cgen_assemble_insn
134 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
135
136 if (!insn.insn)
137 {
138 as_bad (errmsg);
139 return;
140 }
141
142 /* Doesn't really matter what we pass for RELAX_P here. */
143 gas_cgen_finish_insn (insn.insn, insn.buffer,
144 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
145 }
146
147 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
148 Returns BFD_RELOC_NONE if no reloc type can be found.
149 *FIXP may be modified if desired. */
150
151 bfd_reloc_code_real_type
152 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
153 const CGEN_OPERAND *operand,
154 fixS *fixP)
155 {
156 switch (operand->type)
157 {
158 case XC16X_OPERAND_REL:
159 fixP->fx_where += 1;
160 fixP->fx_pcrel = 1;
161 return BFD_RELOC_8_PCREL;
162
163 case XC16X_OPERAND_CADDR:
164 fixP->fx_where += 2;
165 return BFD_RELOC_16;
166
167 case XC16X_OPERAND_UIMM7:
168 fixP->fx_where += 1;
169 fixP->fx_pcrel = 1;
170 return BFD_RELOC_8_PCREL;
171
172 case XC16X_OPERAND_UIMM16:
173 case XC16X_OPERAND_MEMORY:
174 fixP->fx_where += 2;
175 return BFD_RELOC_16;
176
177 case XC16X_OPERAND_UPOF16:
178 fixP->fx_where += 2;
179 return BFD_RELOC_XC16X_POF;
180
181 case XC16X_OPERAND_UPAG16:
182 fixP->fx_where += 2;
183 return BFD_RELOC_XC16X_PAG;
184
185 case XC16X_OPERAND_USEG8:
186 fixP->fx_where += 1;
187 return BFD_RELOC_XC16X_SEG;
188
189 case XC16X_OPERAND_USEG16:
190 case XC16X_OPERAND_USOF16:
191 fixP->fx_where += 2;
192 return BFD_RELOC_XC16X_SOF;
193
194 default : /* avoid -Wall warning */
195 break;
196 }
197
198 fixP->fx_where += 2;
199 return BFD_RELOC_XC16X_SOF;
200 }
201
202 /* Write a value out to the object file, using the appropriate endianness. */
203
204 void
205 md_number_to_chars (char * buf, valueT val, int n)
206 {
207 number_to_chars_littleendian (buf, val, n);
208 }
209
210 void
211 md_show_usage (FILE * stream)
212 {
213 fprintf (stream, _(" XC16X specific command line options:\n"));
214 }
215
216 int
217 md_parse_option (int c ATTRIBUTE_UNUSED,
218 char *arg ATTRIBUTE_UNUSED)
219 {
220 return 0;
221 }
222
223 /* Turn a string in input_line_pointer into a floating point constant
224 of type TYPE, and store the appropriate bytes in *LITP. The number
225 of LITTLENUMS emitted is stored in *SIZEP. An error message is
226 returned, or NULL on OK. */
227
228 /* Equal to MAX_PRECISION in atof-ieee.c. */
229 #define MAX_LITTLENUMS 6
230
231 char *
232 md_atof (int type, char *litP, int *sizeP)
233 {
234 int i;
235 int prec;
236 LITTLENUM_TYPE words[MAX_LITTLENUMS];
237 char *t;
238
239 switch (type)
240 {
241 case 'f':
242 case 'F':
243 case 's':
244 case 'S':
245 prec = 2;
246 break;
247
248 case 'd':
249 case 'D':
250 case 'r':
251 case 'R':
252 prec = 4;
253 break;
254
255 /* FIXME: Some targets allow other format chars for bigger sizes
256 here. */
257
258 default:
259 *sizeP = 0;
260 return _("Bad call to md_atof()");
261 }
262
263 t = atof_ieee (input_line_pointer, type, words);
264 if (t)
265 input_line_pointer = t;
266 *sizeP = prec * sizeof (LITTLENUM_TYPE);
267
268 for (i = prec - 1; i >= 0; i--)
269 {
270 md_number_to_chars (litP, (valueT) words[i],
271 sizeof (LITTLENUM_TYPE));
272 litP += sizeof (LITTLENUM_TYPE);
273 }
274
275 return NULL;
276 }
277
278 valueT
279 md_section_align (segT segment, valueT size)
280 {
281 int align = bfd_get_section_alignment (stdoutput, segment);
282 return ((size + (1 << align) - 1) & (-1 << align));
283 }
284
285 symbolS *
286 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
287 {
288 return NULL;
289 }
290
291 int
292 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
293 segT segment_type ATTRIBUTE_UNUSED)
294 {
295 printf (_("call tomd_estimate_size_before_relax \n"));
296 abort ();
297 }
298
299
300 long
301 md_pcrel_from (fixS *fixP)
302 {
303 long temp_val;
304 temp_val=fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
305
306 return temp_val;
307 }
308
309 long
310 md_pcrel_from_section (fixS *fixP, segT sec)
311 {
312 if (fixP->fx_addsy != (symbolS *) NULL
313 && (! S_IS_DEFINED (fixP->fx_addsy)
314 || S_GET_SEGMENT (fixP->fx_addsy) != sec
315 || S_IS_EXTERNAL (fixP->fx_addsy)
316 || S_IS_WEAK (fixP->fx_addsy)))
317 {
318 return 0;
319 }
320
321 return md_pcrel_from (fixP);
322 }
323
324 arelent *
325 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
326 {
327 arelent *rel;
328 bfd_reloc_code_real_type r_type;
329
330 if (fixp->fx_addsy && fixp->fx_subsy)
331 {
332 if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
333 || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
334 {
335 as_bad_where (fixp->fx_file, fixp->fx_line,
336 "Difference of symbols in different sections is not supported");
337 return NULL;
338 }
339 }
340
341 rel = xmalloc (sizeof (arelent));
342 rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
343 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
344 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
345 rel->addend = fixp->fx_offset;
346
347 r_type = fixp->fx_r_type;
348
349 #define DEBUG 0
350 #if DEBUG
351 fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
352 fflush(stderr);
353 #endif
354
355 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
356 if (rel->howto == NULL)
357 {
358 as_bad_where (fixp->fx_file, fixp->fx_line,
359 _("Cannot represent relocation type %s"),
360 bfd_get_reloc_code_name (r_type));
361 return NULL;
362 }
363
364 return rel;
365 }
366
367 void
368 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
369 {
370 if(!strstr (seg->name,".debug"))
371 {
372 if (*valP < 128)
373 *valP /= 2;
374 if (*valP>268435455)
375 {
376 *valP = *valP * (-1);
377 *valP /= 2;
378 *valP = 256 - (*valP);
379 }
380 }
381
382 gas_cgen_md_apply_fix (fixP, valP, seg);
383 return;
384 }
385
386 void
387 md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
388 segT seg ATTRIBUTE_UNUSED,
389 fragS *fragP ATTRIBUTE_UNUSED)
390 {
391 printf (_("call to md_convert_frag \n"));
392 abort ();
393 }
394
395
This page took 0.037574 seconds and 4 git commands to generate.