* Makefile.am: Remove spurious sanitization marker.
[deliverable/binutils-gdb.git] / gas / config / tc-xc16x.c
CommitLineData
d70c5fc7 1/* tc-xc16x.c -- Assembler for the Infineon XC16X.
20203fb9 2 Copyright 2006, 2007, 2009 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 {
20203fb9 136 as_bad ("%s", errmsg);
d70c5fc7
NC
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
662a2e45 192 default : /* Avoid -Wall warning. */
d70c5fc7
NC
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
d70c5fc7
NC
221char *
222md_atof (int type, char *litP, int *sizeP)
223{
499ac353 224 return ieee_md_atof (type, litP, sizeP, FALSE);
d70c5fc7
NC
225}
226
227valueT
228md_section_align (segT segment, valueT size)
229{
230 int align = bfd_get_section_alignment (stdoutput, segment);
231 return ((size + (1 << align) - 1) & (-1 << align));
232}
233
234symbolS *
235md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
236{
237 return NULL;
238}
239
240int
241md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
242 segT segment_type ATTRIBUTE_UNUSED)
243{
662a2e45 244 printf (_("call to md_estimate_size_before_relax \n"));
d70c5fc7
NC
245 abort ();
246}
247
248
249long
250md_pcrel_from (fixS *fixP)
251{
252 long temp_val;
253 temp_val=fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
254
255 return temp_val;
256}
257
258long
259md_pcrel_from_section (fixS *fixP, segT sec)
260{
261 if (fixP->fx_addsy != (symbolS *) NULL
262 && (! S_IS_DEFINED (fixP->fx_addsy)
263 || S_GET_SEGMENT (fixP->fx_addsy) != sec
264 || S_IS_EXTERNAL (fixP->fx_addsy)
265 || S_IS_WEAK (fixP->fx_addsy)))
266 {
267 return 0;
268 }
269
270 return md_pcrel_from (fixP);
271}
272
273arelent *
274tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
275{
276 arelent *rel;
277 bfd_reloc_code_real_type r_type;
278
279 if (fixp->fx_addsy && fixp->fx_subsy)
280 {
281 if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
282 || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
283 {
284 as_bad_where (fixp->fx_file, fixp->fx_line,
662a2e45 285 _("Difference of symbols in different sections is not supported"));
d70c5fc7
NC
286 return NULL;
287 }
288 }
289
290 rel = xmalloc (sizeof (arelent));
291 rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
292 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
293 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
294 rel->addend = fixp->fx_offset;
295
296 r_type = fixp->fx_r_type;
297
298#define DEBUG 0
299#if DEBUG
300 fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
662a2e45 301 fflush (stderr);
d70c5fc7
NC
302#endif
303
304 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
305 if (rel->howto == NULL)
306 {
307 as_bad_where (fixp->fx_file, fixp->fx_line,
308 _("Cannot represent relocation type %s"),
309 bfd_get_reloc_code_name (r_type));
310 return NULL;
311 }
312
313 return rel;
314}
315
316void
317md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
318{
662a2e45 319 if (!strstr (seg->name,".debug"))
d70c5fc7
NC
320 {
321 if (*valP < 128)
322 *valP /= 2;
323 if (*valP>268435455)
324 {
325 *valP = *valP * (-1);
326 *valP /= 2;
327 *valP = 256 - (*valP);
328 }
329 }
330
331 gas_cgen_md_apply_fix (fixP, valP, seg);
332 return;
333}
334
335void
336md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
337 segT seg ATTRIBUTE_UNUSED,
338 fragS *fragP ATTRIBUTE_UNUSED)
339{
340 printf (_("call to md_convert_frag \n"));
341 abort ();
342}
This page took 0.177213 seconds and 4 git commands to generate.