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