2 tc-pj.c -- Assemble code for Pico Java
3 Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
22 /* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
25 #include "safe-ctype.h"
26 #include "opcode/pj.h"
28 extern const pj_opc_info_t pj_opc_info[512];
30 const char comment_chars[] = "!/";
31 const char line_separator_chars[] = ";";
32 const char line_comment_chars[] = "/!#";
34 static int pending_reloc;
35 static struct hash_control *opcode_hash_control;
39 int ignore ATTRIBUTE_UNUSED;
41 target_big_endian = 0;
46 int ignore ATTRIBUTE_UNUSED;
48 target_big_endian = 1;
51 const pseudo_typeS md_pseudo_table[] = {
57 const char FLT_CHARS[] = "rRsSfFdDxXpP";
58 const char EXP_CHARS[] = "eE";
64 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
67 as_bad (_("confusing relocation expressions"));
68 pending_reloc = BFD_RELOC_PJ_CODE_HI16;
69 input_line_pointer += 5;
72 if (strncmp (input_line_pointer, "%lo16", 5) == 0)
75 as_bad (_("confusing relocation expressions"));
76 pending_reloc = BFD_RELOC_PJ_CODE_LO16;
77 input_line_pointer += 5;
82 /* Parse an expression and then restore the input line pointer. */
85 parse_exp_save_ilp (s, op)
89 char *save = input_line_pointer;
90 input_line_pointer = s;
92 s = input_line_pointer;
93 input_line_pointer = save;
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. */
102 pj_cons_fix_new_pj (frag, where, nbytes, exp)
108 static int rv[5][2] =
110 { BFD_RELOC_8, BFD_RELOC_8 },
111 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
113 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
115 fix_new_exp (frag, where, nbytes, exp, 0,
116 pending_reloc ? pending_reloc
117 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
122 /* Turn a reloc description character from the pj-opc.h table into
123 code which BFD can handle. */
132 return BFD_RELOC_8_PCREL;
137 return BFD_RELOC_PJ_CODE_REL16;
140 return BFD_RELOC_PJ_CODE_DIR16;
142 return BFD_RELOC_PJ_CODE_REL32;
144 return BFD_RELOC_PJ_CODE_DIR32;
150 /* Handler for the ipush fake opcode,
151 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
154 ipush_code (opcode, str)
155 pj_opc_info_t *opcode ATTRIBUTE_UNUSED;
159 char *b = frag_more (6);
164 parse_exp_save_ilp (str + 1, &arg, &mod);
166 as_bad (_("can't have relocation for ipush"));
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);
174 /* Insert names into the opcode table which are really mini macros,
175 not opcodes. The fakeness is inidicated with an opcode of -1. */
178 fake_opcode (name, func)
182 pj_opc_info_t *fake = (pj_opc_info_t *) xmalloc (sizeof (pj_opc_info_t));
185 fake->opcode_next = -1;
186 fake->name = (const char *) func;
187 hash_insert (opcode_hash_control, name, (char *) fake);
190 /* Enter another entry into the opcode hash table so the same opcode
191 can have another name. */
198 hash_insert (opcode_hash_control, new,
199 (char *) hash_find (opcode_hash_control, old));
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. */
209 const pj_opc_info_t *opcode;
210 opcode_hash_control = hash_new ();
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);
216 /* Insert the only fake opcode. */
217 fake_opcode ("ipush", ipush_code);
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");
228 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
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. */
239 unsigned char *op_start;
240 unsigned char *op_end;
243 pj_operan_info operand[3];
245 pj_opc_info_t *opcode;
252 /* Drop leading whitespace. */
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 != ' ';
266 as_bad (_("can't find opcode "));
268 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
273 as_bad (_("unknown opcode %s"), op_start);
277 if (opcode->opcode == -1)
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);
287 output = frag_more (opcode->len);
288 output[idx++] = opcode->opcode;
290 if (opcode->opcode_next != -1)
291 output[idx++] = opcode->opcode_next;
293 for (an = 0; opcode->arg[an]; an++)
297 if (*op_end == ',' && an != 0)
301 as_bad ("expected expresssion");
303 op_end = parse_exp_save_ilp (op_end, &arg);
305 fix_new_exp (frag_now,
306 output - frag_now->fr_literal + idx,
307 ASIZE (opcode->arg[an]),
309 PCREL (opcode->arg[an]),
310 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
312 idx += ASIZE (opcode->arg[an]);
316 while (ISSPACE (*op_end))
320 as_warn ("extra stuff on line ignored");
325 as_bad ("Something forgot to clean up\n");
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. */
335 md_atof (type, litP, sizeP)
341 LITTLENUM_TYPE words[4];
357 return _("bad call to md_atof");
360 t = atof_ieee (input_line_pointer, type, words);
362 input_line_pointer = t;
366 if (!target_big_endian)
368 for (i = prec - 1; i >= 0; i--)
370 md_number_to_chars (litP, (valueT) words[i], 2);
376 for (i = 0; i < prec; i++)
378 md_number_to_chars (litP, (valueT) words[i], 2);
386 CONST char *md_shortopts = "";
388 struct option md_longopts[] = {
390 #define OPTION_LITTLE (OPTION_MD_BASE)
391 #define OPTION_BIG (OPTION_LITTLE + 1)
393 {"little", no_argument, NULL, OPTION_LITTLE},
394 {"big", no_argument, NULL, OPTION_BIG},
395 {NULL, no_argument, NULL, 0}
397 size_t md_longopts_size = sizeof (md_longopts);
400 md_parse_option (c, arg)
402 char *arg ATTRIBUTE_UNUSED;
419 md_show_usage (stream)
422 fprintf (stream, _("\
424 -little generate little endian code\n\
425 -big generate big endian code\n"));
428 /* Apply a fixup to the object file. */
431 md_apply_fix3 (fixP, valP, seg)
434 segT seg ATTRIBUTE_UNUSED;
436 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
437 long val = * (long *) valP;
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. */
446 if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy))
447 val -= S_GET_VALUE (fixP->fx_addsy);
451 switch (fixP->fx_r_type)
453 case BFD_RELOC_VTABLE_INHERIT:
454 case BFD_RELOC_VTABLE_ENTRY:
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;
465 case BFD_RELOC_PJ_CODE_HI16:
468 fixP->fx_addnumber = val & 0xffff;
471 case BFD_RELOC_PJ_CODE_DIR16:
472 case BFD_RELOC_PJ_CODE_LO16:
486 case BFD_RELOC_PJ_CODE_DIR32:
494 if (target_big_endian)
511 if (target_big_endian)
527 if (max != 0 && (val < min || val > max))
528 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
530 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
534 /* Put number into target byte order. Always put values in an
535 executable section into big endian order. */
538 md_number_to_chars (ptr, use, nbytes)
543 if (target_big_endian || now_seg->flags & SEC_CODE)
544 number_to_chars_bigendian (ptr, use, nbytes);
546 number_to_chars_littleendian (ptr, use, nbytes);
549 /* Translate internal representation of relocation info to BFD target
553 tc_gen_reloc (section, fixp)
554 asection *section ATTRIBUTE_UNUSED;
558 bfd_reloc_code_real_type r_type;
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;
565 r_type = fixp->fx_r_type;
566 rel->addend = fixp->fx_addnumber;
567 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
569 if (rel->howto == NULL)
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);