This fixes a compile time error triggered by -Werror=format-security because
[deliverable/binutils-gdb.git] / gas / config / tc-pj.c
1 /* tc-pj.c -- Assemble code for Pico Java
2 Copyright (C) 1999-2014 Free Software Foundation, Inc.
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 3, 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, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
20
21 /* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
22
23 #include "as.h"
24 #include "safe-ctype.h"
25 #include "opcode/pj.h"
26
27 extern const pj_opc_info_t pj_opc_info[512];
28
29 const char comment_chars[] = "!/";
30 const char line_separator_chars[] = ";";
31 const char line_comment_chars[] = "/!#";
32
33 static int pending_reloc;
34 static struct hash_control *opcode_hash_control;
35
36 static void
37 little (int ignore ATTRIBUTE_UNUSED)
38 {
39 target_big_endian = 0;
40 }
41
42 static void
43 big (int ignore ATTRIBUTE_UNUSED)
44 {
45 target_big_endian = 1;
46 }
47
48 const pseudo_typeS md_pseudo_table[] =
49 {
50 {"ml", little, 0},
51 {"mb", big, 0},
52 {0, 0, 0}
53 };
54
55 const char FLT_CHARS[] = "rRsSfFdDxXpP";
56 const char EXP_CHARS[] = "eE";
57
58 void
59 md_operand (expressionS *op)
60 {
61 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
62 {
63 if (pending_reloc)
64 as_bad (_("confusing relocation expressions"));
65 pending_reloc = BFD_RELOC_PJ_CODE_HI16;
66 input_line_pointer += 5;
67 expression (op);
68 }
69
70 if (strncmp (input_line_pointer, "%lo16", 5) == 0)
71 {
72 if (pending_reloc)
73 as_bad (_("confusing relocation expressions"));
74 pending_reloc = BFD_RELOC_PJ_CODE_LO16;
75 input_line_pointer += 5;
76 expression (op);
77 }
78 }
79
80 /* Parse an expression and then restore the input line pointer. */
81
82 static char *
83 parse_exp_save_ilp (char *s, expressionS *op)
84 {
85 char *save = input_line_pointer;
86
87 input_line_pointer = s;
88 expression (op);
89 s = input_line_pointer;
90 input_line_pointer = save;
91 return s;
92 }
93
94 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
95 reloc for a cons. We could use the definition there, except that
96 we want to handle magic pending reloc expressions specially. */
97
98 void
99 pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp)
100 {
101 static int rv[5][2] =
102 { { 0, 0 },
103 { BFD_RELOC_8, BFD_RELOC_8 },
104 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
105 { 0, 0 },
106 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
107
108 fix_new_exp (frag, where, nbytes, exp, 0,
109 pending_reloc ? pending_reloc
110 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
111
112 pending_reloc = 0;
113 }
114
115 /* Turn a reloc description character from the pj-opc.h table into
116 code which BFD can handle. */
117
118 static int
119 c_to_r (int x)
120 {
121 switch (x)
122 {
123 case O_R8:
124 return BFD_RELOC_8_PCREL;
125 case O_U8:
126 case O_8:
127 return BFD_RELOC_8;
128 case O_R16:
129 return BFD_RELOC_PJ_CODE_REL16;
130 case O_U16:
131 case O_16:
132 return BFD_RELOC_PJ_CODE_DIR16;
133 case O_R32:
134 return BFD_RELOC_PJ_CODE_REL32;
135 case O_32:
136 return BFD_RELOC_PJ_CODE_DIR32;
137 }
138 abort ();
139 return 0;
140 }
141
142 /* Handler for the ipush fake opcode,
143 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
144
145 static void
146 ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str)
147 {
148 char *b = frag_more (6);
149 expressionS arg;
150
151 b[0] = 0x11;
152 b[3] = 0xed;
153 parse_exp_save_ilp (str + 1, &arg);
154 if (pending_reloc)
155 {
156 as_bad (_("can't have relocation for ipush"));
157 pending_reloc = 0;
158 }
159
160 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
161 &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
162 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
163 &arg, 0, BFD_RELOC_PJ_CODE_HI16);
164 }
165
166 /* Insert names into the opcode table which are really mini macros,
167 not opcodes. The fakeness is indicated with an opcode of -1. */
168
169 static void
170 fake_opcode (const char *name,
171 void (*func) (struct pj_opc_info_t *, char *))
172 {
173 pj_opc_info_t * fake = xmalloc (sizeof (pj_opc_info_t));
174
175 fake->opcode = -1;
176 fake->opcode_next = -1;
177 fake->u.func = func;
178 hash_insert (opcode_hash_control, name, (char *) fake);
179 }
180
181 /* Enter another entry into the opcode hash table so the same opcode
182 can have another name. */
183
184 static void
185 alias (const char *new_name, const char *old)
186 {
187 hash_insert (opcode_hash_control, new_name,
188 (char *) hash_find (opcode_hash_control, old));
189 }
190
191 /* This function is called once, at assembler startup time. It sets
192 up the hash table with all the opcodes in it, and also initializes
193 some aliases for compatibility with other assemblers. */
194
195 void
196 md_begin (void)
197 {
198 const pj_opc_info_t *opcode;
199 opcode_hash_control = hash_new ();
200
201 /* Insert names into hash table. */
202 for (opcode = pj_opc_info; opcode->u.name; opcode++)
203 hash_insert (opcode_hash_control, opcode->u.name, (char *) opcode);
204
205 /* Insert the only fake opcode. */
206 fake_opcode ("ipush", ipush_code);
207
208 /* Add some aliases for opcode names. */
209 alias ("ifeq_s", "ifeq");
210 alias ("ifne_s", "ifne");
211 alias ("if_icmpge_s", "if_icmpge");
212 alias ("if_icmpne_s", "if_icmpne");
213 alias ("if_icmpeq_s", "if_icmpeq");
214 alias ("if_icmpgt_s", "if_icmpgt");
215 alias ("goto_s", "goto");
216
217 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
218 }
219
220 /* This is the guts of the machine-dependent assembler. STR points to
221 a machine dependent instruction. This function is supposed to emit
222 the frags/bytes it assembles to. */
223
224 void
225 md_assemble (char *str)
226 {
227 char *op_start;
228 char *op_end;
229
230 pj_opc_info_t *opcode;
231 char *output;
232 int idx = 0;
233 char pend;
234
235 int nlen = 0;
236
237 /* Drop leading whitespace. */
238 while (*str == ' ')
239 str++;
240
241 /* Find the op code end. */
242 op_start = str;
243 for (op_end = str;
244 *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
245 op_end++)
246 nlen++;
247
248 pend = *op_end;
249 *op_end = 0;
250
251 if (nlen == 0)
252 as_bad (_("can't find opcode "));
253
254 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
255 *op_end = pend;
256
257 if (opcode == NULL)
258 {
259 as_bad (_("unknown opcode %s"), op_start);
260 return;
261 }
262
263 dwarf2_emit_insn (0);
264 if (opcode->opcode == -1)
265 {
266 /* It's a fake opcode. Dig out the args and pretend that was
267 what we were passed. */
268 (*opcode->u.func) (opcode, op_end);
269 }
270 else
271 {
272 int an;
273
274 output = frag_more (opcode->len);
275 output[idx++] = opcode->opcode;
276
277 if (opcode->opcode_next != -1)
278 output[idx++] = opcode->opcode_next;
279
280 for (an = 0; opcode->arg[an]; an++)
281 {
282 expressionS arg;
283
284 if (*op_end == ',' && an != 0)
285 op_end++;
286
287 if (*op_end == 0)
288 as_bad (_("expected expression"));
289
290 op_end = parse_exp_save_ilp (op_end, &arg);
291
292 fix_new_exp (frag_now,
293 output - frag_now->fr_literal + idx,
294 ASIZE (opcode->arg[an]),
295 &arg,
296 PCREL (opcode->arg[an]),
297 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
298
299 idx += ASIZE (opcode->arg[an]);
300 pending_reloc = 0;
301 }
302
303 while (ISSPACE (*op_end))
304 op_end++;
305
306 if (*op_end != 0)
307 as_warn (_("extra stuff on line ignored"));
308
309 }
310
311 if (pending_reloc)
312 as_bad (_("Something forgot to clean up\n"));
313 }
314
315 char *
316 md_atof (int type, char *litP, int *sizeP)
317 {
318 return ieee_md_atof (type, litP, sizeP, target_big_endian);
319 }
320 \f
321 const char *md_shortopts = "";
322
323 struct option md_longopts[] =
324 {
325 #define OPTION_LITTLE (OPTION_MD_BASE)
326 #define OPTION_BIG (OPTION_LITTLE + 1)
327
328 {"little", no_argument, NULL, OPTION_LITTLE},
329 {"big", no_argument, NULL, OPTION_BIG},
330 {NULL, no_argument, NULL, 0}
331 };
332 size_t md_longopts_size = sizeof (md_longopts);
333
334 int
335 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
336 {
337 switch (c)
338 {
339 case OPTION_LITTLE:
340 little (0);
341 break;
342 case OPTION_BIG:
343 big (0);
344 break;
345 default:
346 return 0;
347 }
348 return 1;
349 }
350
351 void
352 md_show_usage (FILE *stream)
353 {
354 fprintf (stream, _("\
355 PJ options:\n\
356 -little generate little endian code\n\
357 -big generate big endian code\n"));
358 }
359
360 /* Apply a fixup to the object file. */
361
362 void
363 md_apply_fix (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
364 {
365 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
366 long val = *valP;
367 long max, min;
368
369 max = min = 0;
370 switch (fixP->fx_r_type)
371 {
372 case BFD_RELOC_VTABLE_INHERIT:
373 case BFD_RELOC_VTABLE_ENTRY:
374 fixP->fx_done = 0;
375 return;
376
377 case BFD_RELOC_PJ_CODE_REL16:
378 if (val < -0x8000 || val >= 0x7fff)
379 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
380 buf[0] |= (val >> 8) & 0xff;
381 buf[1] = val & 0xff;
382 break;
383
384 case BFD_RELOC_PJ_CODE_HI16:
385 *buf++ = val >> 24;
386 *buf++ = val >> 16;
387 fixP->fx_addnumber = val & 0xffff;
388 break;
389
390 case BFD_RELOC_PJ_CODE_DIR16:
391 case BFD_RELOC_PJ_CODE_LO16:
392 *buf++ = val >> 8;
393 *buf++ = val >> 0;
394
395 max = 0xffff;
396 min = -0xffff;
397 break;
398
399 case BFD_RELOC_8:
400 max = 0xff;
401 min = -0xff;
402 *buf++ = val;
403 break;
404
405 case BFD_RELOC_PJ_CODE_DIR32:
406 *buf++ = val >> 24;
407 *buf++ = val >> 16;
408 *buf++ = val >> 8;
409 *buf++ = val >> 0;
410 break;
411
412 case BFD_RELOC_32:
413 if (target_big_endian)
414 {
415 *buf++ = val >> 24;
416 *buf++ = val >> 16;
417 *buf++ = val >> 8;
418 *buf++ = val >> 0;
419 }
420 else
421 {
422 *buf++ = val >> 0;
423 *buf++ = val >> 8;
424 *buf++ = val >> 16;
425 *buf++ = val >> 24;
426 }
427 break;
428
429 case BFD_RELOC_16:
430 if (target_big_endian)
431 {
432 *buf++ = val >> 8;
433 *buf++ = val >> 0;
434 }
435 else
436 {
437 *buf++ = val >> 0;
438 *buf++ = val >> 8;
439 }
440 break;
441
442 default:
443 abort ();
444 }
445
446 if (max != 0 && (val < min || val > max))
447 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
448
449 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
450 fixP->fx_done = 1;
451 }
452
453 /* Put number into target byte order. Always put values in an
454 executable section into big endian order. */
455
456 void
457 md_number_to_chars (char *ptr, valueT use, int nbytes)
458 {
459 if (target_big_endian || now_seg->flags & SEC_CODE)
460 number_to_chars_bigendian (ptr, use, nbytes);
461 else
462 number_to_chars_littleendian (ptr, use, nbytes);
463 }
464
465 /* Translate internal representation of relocation info to BFD target
466 format. */
467
468 arelent *
469 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
470 {
471 arelent *rel;
472 bfd_reloc_code_real_type r_type;
473
474 rel = xmalloc (sizeof (arelent));
475 rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
476 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
477 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
478
479 r_type = fixp->fx_r_type;
480 rel->addend = fixp->fx_addnumber;
481 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
482
483 if (rel->howto == NULL)
484 {
485 as_bad_where (fixp->fx_file, fixp->fx_line,
486 _("Cannot represent relocation type %s"),
487 bfd_get_reloc_code_name (r_type));
488 /* Set howto to a garbage value so that we can keep going. */
489 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
490 gas_assert (rel->howto != NULL);
491 }
492
493 return rel;
494 }
This page took 0.039785 seconds and 4 git commands to generate.