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