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