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