* config/tc-sparc.c (s_register): Only declare #ifdef OBJ_ELF.
[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
ILT
36
37static void
38little (ignore)
39 int ignore ATTRIBUTE_UNUSED;
40{
41 target_big_endian = 0;
42}
43
44static void
45big (ignore)
46 int ignore ATTRIBUTE_UNUSED;
47{
48 target_big_endian = 1;
49}
50
041dd5a9
ILT
51const pseudo_typeS md_pseudo_table[] = {
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
61md_operand (op)
62 expressionS *op;
63{
64 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
65 {
66 if (pending_reloc)
a2429eb5 67 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
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)
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 *
85parse_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
101void
102pj_cons_fix_new_pj (frag, where, nbytes, exp)
103 fragS *frag;
104 int where;
105 int nbytes;
106 expressionS *exp;
107{
a2429eb5 108 static int rv[5][2] =
041dd5a9
ILT
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
a2429eb5 115 fix_new_exp (frag, where, nbytes, exp, 0,
041dd5a9 116 pending_reloc ? pending_reloc
a2429eb5 117 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
041dd5a9
ILT
118
119 pending_reloc = 0;
120}
121
041dd5a9 122/* Turn a reloc description character from the pj-opc.h table into
a2429eb5 123 code which BFD can handle. */
041dd5a9
ILT
124
125static int
126c_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
041dd5a9 150/* Handler for the ipush fake opcode,
a2429eb5 151 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
041dd5a9
ILT
152
153static void
154ipush_code (opcode, str)
a2429eb5 155 pj_opc_info_t *opcode ATTRIBUTE_UNUSED;
041dd5a9
ILT
156 char *str;
157{
158 int mod = 0;
159 char *b = frag_more (6);
160 expressionS arg;
a2429eb5 161
041dd5a9
ILT
162 b[0] = 0x11;
163 b[3] = 0xed;
164 parse_exp_save_ilp (str + 1, &arg, &mod);
165 if (mod)
a2429eb5 166 as_bad (_("can't have relocation for ipush"));
041dd5a9 167
a2429eb5
NC
168 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
169 &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
041dd5a9 170 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
a2429eb5 171 &arg, 0, BFD_RELOC_PJ_CODE_HI16);
041dd5a9
ILT
172}
173
174/* Insert names into the opcode table which are really mini macros,
a2429eb5 175 not opcodes. The fakeness is inidicated with an opcode of -1. */
041dd5a9
ILT
176
177static void
a2429eb5
NC
178fake_opcode (name, func)
179 const char *name;
041dd5a9
ILT
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
041dd5a9 190/* Enter another entry into the opcode hash table so the same opcode
a2429eb5
NC
191 can have another name. */
192
041dd5a9 193static void
a2429eb5
NC
194alias (new, old)
195 const char *new;
041dd5a9
ILT
196 const char *old;
197{
198 hash_insert (opcode_hash_control, new,
199 (char *) hash_find (opcode_hash_control, old));
200}
201
041dd5a9
ILT
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
a2429eb5 204 some aliases for compatibility with other assemblers. */
041dd5a9
ILT
205
206void
207md_begin ()
208{
209 const pj_opc_info_t *opcode;
210 opcode_hash_control = hash_new ();
211
a2429eb5 212 /* Insert names into hash table. */
041dd5a9
ILT
213 for (opcode = pj_opc_info; opcode->name; opcode++)
214 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
215
a2429eb5 216 /* Insert the only fake opcode. */
041dd5a9
ILT
217 fake_opcode ("ipush", ipush_code);
218
a2429eb5 219 /* Add some aliases for opcode names. */
041dd5a9
ILT
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
a2429eb5
NC
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. */
041dd5a9
ILT
234
235void
236md_assemble (str)
237 char *str;
238{
239 unsigned char *op_start;
240 unsigned char *op_end;
241
a2429eb5
NC
242#if 0
243 pj_operan_info operand[3];
244#endif
041dd5a9
ILT
245 pj_opc_info_t *opcode;
246 char *output;
247 int idx = 0;
248 char pend;
249
250 int nlen = 0;
251
a2429eb5 252 /* Drop leading whitespace. */
041dd5a9
ILT
253 while (*str == ' ')
254 str++;
255
a2429eb5 256 /* Find the op code end. */
041dd5a9
ILT
257 for (op_start = op_end = (unsigned char *) (str);
258 *op_end && !is_end_of_line[*op_end] && *op_end != ' ';
a2429eb5 259 op_end++)
041dd5a9
ILT
260 nlen++;
261
262 pend = *op_end;
263 *op_end = 0;
264
265 if (nlen == 0)
a2429eb5 266 as_bad (_("can't find opcode "));
041dd5a9
ILT
267
268 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
269 *op_end = pend;
270
271 if (opcode == NULL)
272 {
a2429eb5 273 as_bad (_("unknown opcode %s"), op_start);
041dd5a9
ILT
274 return;
275 }
276
277 if (opcode->opcode == -1)
278 {
a2429eb5
NC
279 /* It's a fake opcode. Dig out the args and pretend that was
280 what we were passed. */
bc805888 281 ((void (*) ()) opcode->name) (opcode, op_end);
041dd5a9
ILT
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
a2429eb5 305 fix_new_exp (frag_now,
041dd5a9
ILT
306 output - frag_now->fr_literal + idx,
307 ASIZE (opcode->arg[an]),
308 &arg,
a2429eb5 309 PCREL (opcode->arg[an]),
041dd5a9
ILT
310 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
311
312 idx += ASIZE (opcode->arg[an]);
313 pending_reloc = 0;
314 }
315
3882b010 316 while (ISSPACE (*op_end))
041dd5a9
ILT
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
a2429eb5
NC
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
041dd5a9
ILT
334char *
335md_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;
a2429eb5 357 return _("bad call to md_atof");
041dd5a9
ILT
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
5a38dc70 386const char *md_shortopts = "";
041dd5a9
ILT
387
388struct 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};
397size_t md_longopts_size = sizeof (md_longopts);
398
399int
400md_parse_option (c, arg)
401 int c;
a2429eb5 402 char *arg ATTRIBUTE_UNUSED;
041dd5a9
ILT
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
418void
419md_show_usage (stream)
420 FILE *stream;
421{
a2429eb5 422 fprintf (stream, _("\
041dd5a9
ILT
423PJ options:\n\
424-little generate little endian code\n\
425-big generate big endian code\n"));
426}
427
041dd5a9
ILT
428/* Apply a fixup to the object file. */
429
94f592af
NC
430void
431md_apply_fix3 (fixP, valP, seg)
041dd5a9 432 fixS *fixP;
94f592af
NC
433 valueT * valP;
434 segT seg ATTRIBUTE_UNUSED;
041dd5a9
ILT
435{
436 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
a161fe53 437 long val = *valP;
041dd5a9
ILT
438 long max, min;
439 int shift;
440
041dd5a9
ILT
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;
94f592af 448 return;
041dd5a9
ILT
449
450 case BFD_RELOC_PJ_CODE_REL16:
451 if (val < -0x8000 || val >= 0x7fff)
a2429eb5 452 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
041dd5a9
ILT
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 }
a2429eb5 493 else
041dd5a9
ILT
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
041dd5a9
ILT
515 default:
516 abort ();
517 }
518
519 if (max != 0 && (val < min || val > max))
a2429eb5 520 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
041dd5a9 521
94f592af
NC
522 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
523 fixP->fx_done = 1;
041dd5a9
ILT
524}
525
526/* Put number into target byte order. Always put values in an
a2429eb5 527 executable section into big endian order. */
041dd5a9
ILT
528
529void
530md_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
041dd5a9 541/* Translate internal representation of relocation info to BFD target
a2429eb5 542 format. */
041dd5a9
ILT
543
544arelent *
545tc_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,
a2429eb5 564 _("Cannot represent relocation type %s"),
041dd5a9
ILT
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.208408 seconds and 4 git commands to generate.