* elf.c (_bfd_elf_make_section_from_shdr): Set SEC_THREAD_LOCAL
[platform/upstream/binutils.git] / gas / config / tc-pj.c
1 /*-
2    tc-pj.c -- Assemble code for Pico Java
3    Copyright 1999, 2000, 2001 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 = * (long *) valP;
438   long max, min;
439   int shift;
440
441   /* adjust_reloc_syms won't convert a reloc against a weak symbol
442      into a reloc against a section, but bfd_install_relocation will
443      screw up if the symbol is defined, so we have to adjust val here
444      to avoid the screw up later.  */
445
446   if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy))
447     val -= S_GET_VALUE (fixP->fx_addsy);
448
449   max = min = 0;
450   shift = 0;
451   switch (fixP->fx_r_type)
452     {
453     case BFD_RELOC_VTABLE_INHERIT:
454     case BFD_RELOC_VTABLE_ENTRY:
455       fixP->fx_done = 0;
456       return;
457
458     case BFD_RELOC_PJ_CODE_REL16:
459       if (val < -0x8000 || val >= 0x7fff)
460         as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
461       buf[0] |= (val >> 8) & 0xff;
462       buf[1] = val & 0xff;
463       break;
464
465     case BFD_RELOC_PJ_CODE_HI16:
466       *buf++ = val >> 24;
467       *buf++ = val >> 16;
468       fixP->fx_addnumber = val & 0xffff;
469       break;
470
471     case BFD_RELOC_PJ_CODE_DIR16:
472     case BFD_RELOC_PJ_CODE_LO16:
473       *buf++ = val >> 8;
474       *buf++ = val >> 0;
475
476       max = 0xffff;
477       min = -0xffff;
478       break;
479
480     case BFD_RELOC_8:
481       max = 0xff;
482       min = -0xff;
483       *buf++ = val;
484       break;
485
486     case BFD_RELOC_PJ_CODE_DIR32:
487       *buf++ = val >> 24;
488       *buf++ = val >> 16;
489       *buf++ = val >> 8;
490       *buf++ = val >> 0;
491       break;
492
493     case BFD_RELOC_32:
494       if (target_big_endian)
495         {
496           *buf++ = val >> 24;
497           *buf++ = val >> 16;
498           *buf++ = val >> 8;
499           *buf++ = val >> 0;
500         }
501       else
502         {
503           *buf++ = val >> 0;
504           *buf++ = val >> 8;
505           *buf++ = val >> 16;
506           *buf++ = val >> 24;
507         }
508       break;
509
510     case BFD_RELOC_16:
511       if (target_big_endian)
512         {
513           *buf++ = val >> 8;
514           *buf++ = val >> 0;
515         }
516       else
517         {
518           *buf++ = val >> 0;
519           *buf++ = val >> 8;
520         }
521       break;
522
523     default:
524       abort ();
525     }
526
527   if (max != 0 && (val < min || val > max))
528     as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
529
530   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
531     fixP->fx_done = 1;
532 }
533
534 /* Put number into target byte order.  Always put values in an
535    executable section into big endian order.  */
536
537 void
538 md_number_to_chars (ptr, use, nbytes)
539      char *ptr;
540      valueT use;
541      int nbytes;
542 {
543   if (target_big_endian || now_seg->flags & SEC_CODE)
544     number_to_chars_bigendian (ptr, use, nbytes);
545   else
546     number_to_chars_littleendian (ptr, use, nbytes);
547 }
548
549 /* Translate internal representation of relocation info to BFD target
550    format.  */
551
552 arelent *
553 tc_gen_reloc (section, fixp)
554      asection *section ATTRIBUTE_UNUSED;
555      fixS *fixp;
556 {
557   arelent *rel;
558   bfd_reloc_code_real_type r_type;
559
560   rel = (arelent *) xmalloc (sizeof (arelent));
561   rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
562   *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
563   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
564
565   r_type = fixp->fx_r_type;
566   rel->addend = fixp->fx_addnumber;
567   rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
568
569   if (rel->howto == NULL)
570     {
571       as_bad_where (fixp->fx_file, fixp->fx_line,
572                     _("Cannot represent relocation type %s"),
573                     bfd_get_reloc_code_name (r_type));
574       /* Set howto to a garbage value so that we can keep going.  */
575       rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
576       assert (rel->howto != NULL);
577     }
578
579   return rel;
580 }