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