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