Remove uses of ctype.h
[deliverable/binutils-gdb.git] / gas / config / tc-ip2k.c
1 /* tc-ip2k.c -- Assembler for the Scenix IP2xxx.
2 Copyright (C) 2000, 2002, 2003 Free Software Foundation.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include <stdio.h>
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/ip2k-desc.h"
26 #include "opcodes/ip2k-opc.h"
27 #include "cgen.h"
28 #include "elf/common.h"
29 #include "elf/ip2k.h"
30 #include "libbfd.h"
31
32 /* Structure to hold all of the different components describing
33 an individual instruction. */
34 typedef struct
35 {
36 const CGEN_INSN * insn;
37 const CGEN_INSN * orig_insn;
38 CGEN_FIELDS fields;
39 #if CGEN_INT_INSN_P
40 CGEN_INSN_INT buffer [1];
41 #define INSN_VALUE(buf) (*(buf))
42 #else
43 unsigned char buffer [CGEN_MAX_INSN_SIZE];
44 #define INSN_VALUE(buf) (buf)
45 #endif
46 char * addr;
47 fragS * frag;
48 int num_fixups;
49 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
50 int indices [MAX_OPERAND_INSTANCES];
51 }
52 ip2k_insn;
53
54 const char comment_chars[] = ";";
55 const char line_comment_chars[] = "#";
56 const char line_separator_chars[] = "";
57 const char EXP_CHARS[] = "eE";
58 const char FLT_CHARS[] = "dD";
59
60 static void ip2k_elf_section_text (int);
61 static void ip2k_elf_section_rtn (int);
62
63 /* The target specific pseudo-ops which we support. */
64 const pseudo_typeS md_pseudo_table[] =
65 {
66 { "text", ip2k_elf_section_text, 0 },
67 { "sect", ip2k_elf_section_rtn, 0 },
68 { NULL, NULL, 0 }
69 };
70
71 \f
72
73 #define OPTION_CPU_IP2022 (OPTION_MD_BASE)
74 #define OPTION_CPU_IP2022EXT (OPTION_MD_BASE+1)
75
76 struct option md_longopts[] =
77 {
78 { "mip2022", no_argument, NULL, OPTION_CPU_IP2022 },
79 { "mip2022ext", no_argument, NULL, OPTION_CPU_IP2022EXT },
80 { NULL, no_argument, NULL, 0 },
81 };
82 size_t md_longopts_size = sizeof (md_longopts);
83
84 const char * md_shortopts = "";
85
86 /* Flag to detect when switching to code section where insn alignment is
87 implied. */
88 static int force_code_align = 0;
89
90 /* Mach selected from command line. */
91 int ip2k_mach = 0;
92 unsigned ip2k_mach_bitmask = 0;
93
94 int
95 md_parse_option (c, arg)
96 int c ATTRIBUTE_UNUSED;
97 char * arg ATTRIBUTE_UNUSED;
98 {
99 switch (c)
100 {
101 case OPTION_CPU_IP2022:
102 ip2k_mach = bfd_mach_ip2022;
103 ip2k_mach_bitmask = 1 << MACH_IP2022;
104 break;
105
106 case OPTION_CPU_IP2022EXT:
107 ip2k_mach = bfd_mach_ip2022ext;
108 ip2k_mach_bitmask = 1 << MACH_IP2022EXT;
109 break;
110
111 default:
112 return 0;
113 }
114
115 return 1;
116 }
117
118
119 void
120 md_show_usage (stream)
121 FILE * stream;
122 {
123 fprintf (stream, _("IP2K specific command line options:\n"));
124 fprintf (stream, _(" -mip2022 restrict to IP2022 insns \n"));
125 fprintf (stream, _(" -mip2022ext permit extended IP2022 insn\n"));
126 }
127
128 \f
129 void
130 md_begin ()
131 {
132 /* Initialize the `cgen' interface. */
133
134 /* Set the machine number and endian. */
135 gas_cgen_cpu_desc = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_MACHS,
136 ip2k_mach_bitmask,
137 CGEN_CPU_OPEN_ENDIAN,
138 CGEN_ENDIAN_BIG,
139 CGEN_CPU_OPEN_END);
140 ip2k_cgen_init_asm (gas_cgen_cpu_desc);
141
142 /* This is a callback from cgen to gas to parse operands. */
143 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
144
145 /* Set the machine type. */
146 bfd_default_set_arch_mach (stdoutput, bfd_arch_ip2k, ip2k_mach);
147 }
148
149
150 void
151 md_assemble (str)
152 char * str;
153 {
154 ip2k_insn insn;
155 char * errmsg;
156
157 /* Initialize GAS's cgen interface for a new instruction. */
158 gas_cgen_init_parse ();
159
160 insn.insn = ip2k_cgen_assemble_insn
161 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
162
163 if (!insn.insn)
164 {
165 as_bad ("%s", errmsg);
166 return;
167 }
168
169 /* Check for special relocation required by SKIP instructions. */
170 if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_SKIPA))
171 /* Unconditional skip has a 1-bit relocation of the current pc, so
172 that we emit either sb pcl.0 or snb pcl.0 depending on whether
173 the PCL (pc + 2) >> 1 is odd or even. */
174 {
175 enum cgen_parse_operand_result result_type;
176 long value;
177 const char *curpc_plus_2 = ".+2";
178 const char *err;
179
180 err = cgen_parse_address (gas_cgen_cpu_desc, & curpc_plus_2,
181 IP2K_OPERAND_ADDR16CJP,
182 BFD_RELOC_IP2K_PC_SKIP,
183 & result_type, & value);
184 if (err)
185 {
186 as_bad ("%s", err);
187 return;
188 }
189 }
190
191 /* Doesn't really matter what we pass for RELAX_P here. */
192 gas_cgen_finish_insn (insn.insn, insn.buffer,
193 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
194 }
195
196 valueT
197 md_section_align (segment, size)
198 segT segment;
199 valueT size;
200 {
201 int align = bfd_get_section_alignment (stdoutput, segment);
202
203 return ((size + (1 << align) - 1) & (-1 << align));
204 }
205
206
207 symbolS *
208 md_undefined_symbol (name)
209 char * name ATTRIBUTE_UNUSED;
210 {
211 return 0;
212 }
213 \f
214 int
215 md_estimate_size_before_relax (fragP, segment)
216 fragS * fragP ATTRIBUTE_UNUSED;
217 segT segment ATTRIBUTE_UNUSED;
218 {
219 as_fatal (_("md_estimate_size_before_relax\n"));
220 return 1;
221 }
222
223
224 /* *fragP has been relaxed to its final size, and now needs to have
225 the bytes inside it modified to conform to the new size.
226
227 Called after relaxation is finished.
228 fragP->fr_type == rs_machine_dependent.
229 fragP->fr_subtype is the subtype of what the address relaxed to. */
230
231 void
232 md_convert_frag (abfd, sec, fragP)
233 bfd * abfd ATTRIBUTE_UNUSED;
234 segT sec ATTRIBUTE_UNUSED;
235 fragS * fragP ATTRIBUTE_UNUSED;
236 {
237 }
238
239 \f
240 /* Functions concerning relocs. */
241
242 long
243 md_pcrel_from (fixP)
244 fixS *fixP;
245 {
246 as_fatal (_("md_pcrel_from\n"));
247
248 /* Return the address of the delay slot. */
249 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
250 }
251
252
253 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
254 Returns BFD_RELOC_NONE if no reloc type can be found.
255 *FIXP may be modified if desired. */
256
257 bfd_reloc_code_real_type
258 md_cgen_lookup_reloc (insn, operand, fixP)
259 const CGEN_INSN * insn ATTRIBUTE_UNUSED;
260 const CGEN_OPERAND * operand;
261 fixS * fixP ATTRIBUTE_UNUSED;
262 {
263 bfd_reloc_code_real_type result;
264
265 result = BFD_RELOC_NONE;
266
267 switch (operand->type)
268 {
269 case IP2K_OPERAND_FR:
270 case IP2K_OPERAND_ADDR16L:
271 case IP2K_OPERAND_ADDR16H:
272 case IP2K_OPERAND_LIT8:
273 /* These may have been processed at parse time. */
274 if (fixP->fx_cgen.opinfo != 0)
275 result = fixP->fx_cgen.opinfo;
276 fixP->fx_no_overflow = 1;
277 break;
278
279 case IP2K_OPERAND_ADDR16CJP:
280 result = fixP->fx_cgen.opinfo;
281 if (result == 0 || result == BFD_RELOC_NONE)
282 result = BFD_RELOC_IP2K_ADDR16CJP;
283 fixP->fx_no_overflow = 1;
284 break;
285
286 case IP2K_OPERAND_ADDR16P:
287 result = BFD_RELOC_IP2K_PAGE3;
288 fixP->fx_no_overflow = 1;
289 break;
290
291 default:
292 result = BFD_RELOC_NONE;
293 break;
294 }
295
296 return result;
297 }
298
299
300 /* Write a value out to the object file, using the appropriate endianness. */
301
302 void
303 md_number_to_chars (buf, val, n)
304 char * buf;
305 valueT val;
306 int n;
307 {
308 number_to_chars_bigendian (buf, val, n);
309 }
310
311 /* Turn a string in input_line_pointer into a floating point constant of type
312 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
313 emitted is stored in *sizeP . An error message is returned, or NULL on
314 OK. */
315
316 /* Equal to MAX_PRECISION in atof-ieee.c */
317 #define MAX_LITTLENUMS 6
318
319 char *
320 md_atof (type, litP, sizeP)
321 char type;
322 char * litP;
323 int * sizeP;
324 {
325 int prec;
326 LITTLENUM_TYPE words [MAX_LITTLENUMS];
327 LITTLENUM_TYPE *wordP;
328 char * t;
329 char * atof_ieee PARAMS ((char *, int, LITTLENUM_TYPE *));
330
331 switch (type)
332 {
333 case 'f':
334 case 'F':
335 case 's':
336 case 'S':
337 prec = 2;
338 break;
339
340 case 'd':
341 case 'D':
342 case 'r':
343 case 'R':
344 prec = 4;
345 break;
346
347 /* FIXME: Some targets allow other format chars for bigger sizes here. */
348
349 default:
350 * sizeP = 0;
351 return _("Bad call to md_atof()");
352 }
353
354 t = atof_ieee (input_line_pointer, type, words);
355 if (t)
356 input_line_pointer = t;
357 * sizeP = prec * sizeof (LITTLENUM_TYPE);
358
359 /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
360 the ip2k endianness. */
361 for (wordP = words; prec--;)
362 {
363 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
364 litP += sizeof (LITTLENUM_TYPE);
365 }
366
367 return 0;
368 }
369
370
371 /* See whether we need to force a relocation into the output file.
372 Force most of them, since the linker's bfd relocation engine
373 understands range limits better than gas' cgen fixup engine.
374 Consider the case of a fixup intermediate value being larger than
375 the instruction it will be eventually encoded within. */
376
377 int
378 ip2k_force_relocation (fix)
379 fixS * fix;
380 {
381 switch (fix->fx_r_type)
382 {
383 case BFD_RELOC_IP2K_FR9:
384 case BFD_RELOC_IP2K_FR_OFFSET:
385 case BFD_RELOC_IP2K_BANK:
386 case BFD_RELOC_IP2K_ADDR16CJP:
387 case BFD_RELOC_IP2K_PAGE3:
388 case BFD_RELOC_IP2K_LO8DATA:
389 case BFD_RELOC_IP2K_HI8DATA:
390 case BFD_RELOC_IP2K_EX8DATA:
391 case BFD_RELOC_IP2K_LO8INSN:
392 case BFD_RELOC_IP2K_HI8INSN:
393 case BFD_RELOC_IP2K_PC_SKIP:
394 case BFD_RELOC_IP2K_TEXT:
395 return 1;
396
397 case BFD_RELOC_16:
398 if (fix->fx_subsy && S_IS_DEFINED (fix->fx_subsy)
399 && fix->fx_addsy && S_IS_DEFINED (fix->fx_addsy)
400 && (S_GET_SEGMENT (fix->fx_addsy)->flags & SEC_CODE))
401 {
402 fix->fx_r_type = BFD_RELOC_IP2K_TEXT;
403 return 0;
404 }
405 break;
406
407 default:
408 break;
409 }
410
411 return generic_force_reloc (fix);
412 }
413
414 void
415 ip2k_apply_fix3 (fixP, valueP, seg)
416 fixS *fixP;
417 valueT *valueP;
418 segT seg;
419 {
420 if (fixP->fx_r_type == BFD_RELOC_IP2K_TEXT
421 && ! fixP->fx_addsy
422 && ! fixP->fx_subsy)
423 {
424 *valueP = ((int)(*valueP)) / 2;
425 fixP->fx_r_type = BFD_RELOC_16;
426 }
427 else if (fixP->fx_r_type == BFD_RELOC_UNUSED + IP2K_OPERAND_FR)
428 {
429 /* Must be careful when we are fixing up an FR. We could be
430 fixing up an offset to (SP) or (DP) in which case we don't
431 want to step on the top 2 bits of the FR operand. The
432 gas_cgen_md_apply_fix3 doesn't know any better and overwrites
433 the entire operand. We counter this by adding the bits
434 to the new value. */
435 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
436
437 /* Canonical name, since used a lot. */
438 CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
439 CGEN_INSN_INT insn_value
440 = cgen_get_insn_value (cd, where,
441 CGEN_INSN_BITSIZE (fixP->fx_cgen.insn));
442 /* Preserve (DP) or (SP) specification. */
443 *valueP += (insn_value & 0x180);
444 }
445
446 gas_cgen_md_apply_fix3 (fixP, valueP, seg);
447 }
448
449 int
450 ip2k_elf_section_flags (flags, attr, type)
451 int flags;
452 int attr ATTRIBUTE_UNUSED;
453 int type ATTRIBUTE_UNUSED;
454 {
455 /* This is used to detect when the section changes to an executable section.
456 This function is called by the elf section processing. When we note an
457 executable section specifier we set an internal flag to denote when
458 word alignment should be forced. */
459 if (flags & SEC_CODE)
460 force_code_align = 1;
461
462 return flags;
463 }
464
465 static void
466 ip2k_elf_section_rtn (int i)
467 {
468 obj_elf_section(i);
469
470 if (force_code_align)
471 {
472 /* The s_align_ptwo function expects that we are just after a .align
473 directive and it will either try and read the align value or stop
474 if end of line so we must fake it out so it thinks we are at the
475 end of the line. */
476 char *old_input_line_pointer = input_line_pointer;
477 input_line_pointer = "\n";
478 s_align_ptwo (1);
479 force_code_align = 0;
480 /* Restore. */
481 input_line_pointer = old_input_line_pointer;
482 }
483 }
484
485 static void
486 ip2k_elf_section_text (int i)
487 {
488 char *old_input_line_pointer;
489 obj_elf_text(i);
490
491 /* the s_align_ptwo function expects that we are just after a .align
492 directive and it will either try and read the align value or stop if
493 end of line so we must fake it out so it thinks we are at the end of
494 the line. */
495 old_input_line_pointer = input_line_pointer;
496 input_line_pointer = "\n";
497 s_align_ptwo (1);
498 force_code_align = 0;
499 /* Restore. */
500 input_line_pointer = old_input_line_pointer;
501 }
This page took 0.04607 seconds and 5 git commands to generate.