2 tc-pj.c -- Assemble code for Pico Java
3 Copyright 1999, 2000, 2001, 2002, 2003, 2005
4 Free Software Foundation, Inc.
6 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
23 /* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
26 #include "safe-ctype.h"
27 #include "opcode/pj.h"
29 extern const pj_opc_info_t pj_opc_info
[512];
31 const char comment_chars
[] = "!/";
32 const char line_separator_chars
[] = ";";
33 const char line_comment_chars
[] = "/!#";
35 static int pending_reloc
;
36 static struct hash_control
*opcode_hash_control
;
42 static char *parse_exp_save_ilp
43 PARAMS ((char *, expressionS
*));
46 static void ipush_code
47 PARAMS ((pj_opc_info_t
*, char *));
48 static void fake_opcode
49 PARAMS ((const char *, void (*) (struct pj_opc_info_t
*, char *)));
51 PARAMS ((const char *, const char *));
55 int ignore ATTRIBUTE_UNUSED
;
57 target_big_endian
= 0;
62 int ignore ATTRIBUTE_UNUSED
;
64 target_big_endian
= 1;
67 const pseudo_typeS md_pseudo_table
[] = {
73 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
74 const char EXP_CHARS
[] = "eE";
80 if (strncmp (input_line_pointer
, "%hi16", 5) == 0)
83 as_bad (_("confusing relocation expressions"));
84 pending_reloc
= BFD_RELOC_PJ_CODE_HI16
;
85 input_line_pointer
+= 5;
88 if (strncmp (input_line_pointer
, "%lo16", 5) == 0)
91 as_bad (_("confusing relocation expressions"));
92 pending_reloc
= BFD_RELOC_PJ_CODE_LO16
;
93 input_line_pointer
+= 5;
98 /* Parse an expression and then restore the input line pointer. */
101 parse_exp_save_ilp (s
, op
)
105 char *save
= input_line_pointer
;
106 input_line_pointer
= s
;
108 s
= input_line_pointer
;
109 input_line_pointer
= save
;
113 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
114 reloc for a cons. We could use the definition there, except that
115 we want to handle magic pending reloc expressions specially. */
118 pj_cons_fix_new_pj (frag
, where
, nbytes
, exp
)
124 static int rv
[5][2] =
126 { BFD_RELOC_8
, BFD_RELOC_8
},
127 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
129 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
131 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
132 pending_reloc
? pending_reloc
133 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
138 /* Turn a reloc description character from the pj-opc.h table into
139 code which BFD can handle. */
148 return BFD_RELOC_8_PCREL
;
153 return BFD_RELOC_PJ_CODE_REL16
;
156 return BFD_RELOC_PJ_CODE_DIR16
;
158 return BFD_RELOC_PJ_CODE_REL32
;
160 return BFD_RELOC_PJ_CODE_DIR32
;
166 /* Handler for the ipush fake opcode,
167 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
170 ipush_code (opcode
, str
)
171 pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
;
174 char *b
= frag_more (6);
179 parse_exp_save_ilp (str
+ 1, &arg
);
182 as_bad (_("can't have relocation for ipush"));
186 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
187 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
188 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
189 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
192 /* Insert names into the opcode table which are really mini macros,
193 not opcodes. The fakeness is indicated with an opcode of -1. */
196 fake_opcode (name
, func
)
198 void (*func
) PARAMS ((struct pj_opc_info_t
*, char *));
200 pj_opc_info_t
*fake
= (pj_opc_info_t
*) xmalloc (sizeof (pj_opc_info_t
));
203 fake
->opcode_next
= -1;
205 hash_insert (opcode_hash_control
, name
, (char *) fake
);
208 /* Enter another entry into the opcode hash table so the same opcode
209 can have another name. */
216 hash_insert (opcode_hash_control
, new,
217 (char *) hash_find (opcode_hash_control
, old
));
220 /* This function is called once, at assembler startup time. It sets
221 up the hash table with all the opcodes in it, and also initializes
222 some aliases for compatibility with other assemblers. */
227 const pj_opc_info_t
*opcode
;
228 opcode_hash_control
= hash_new ();
230 /* Insert names into hash table. */
231 for (opcode
= pj_opc_info
; opcode
->u
.name
; opcode
++)
232 hash_insert (opcode_hash_control
, opcode
->u
.name
, (char *) opcode
);
234 /* Insert the only fake opcode. */
235 fake_opcode ("ipush", ipush_code
);
237 /* Add some aliases for opcode names. */
238 alias ("ifeq_s", "ifeq");
239 alias ("ifne_s", "ifne");
240 alias ("if_icmpge_s", "if_icmpge");
241 alias ("if_icmpne_s", "if_icmpne");
242 alias ("if_icmpeq_s", "if_icmpeq");
243 alias ("if_icmpgt_s", "if_icmpgt");
244 alias ("goto_s", "goto");
246 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
249 /* This is the guts of the machine-dependent assembler. STR points to
250 a machine dependent instruction. This function is supposed to emit
251 the frags/bytes it assembles to. */
260 pj_opc_info_t
*opcode
;
267 /* Drop leading whitespace. */
271 /* Find the op code end. */
274 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
282 as_bad (_("can't find opcode "));
284 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
289 as_bad (_("unknown opcode %s"), op_start
);
293 if (opcode
->opcode
== -1)
295 /* It's a fake opcode. Dig out the args and pretend that was
296 what we were passed. */
297 (*opcode
->u
.func
) (opcode
, op_end
);
303 output
= frag_more (opcode
->len
);
304 output
[idx
++] = opcode
->opcode
;
306 if (opcode
->opcode_next
!= -1)
307 output
[idx
++] = opcode
->opcode_next
;
309 for (an
= 0; opcode
->arg
[an
]; an
++)
313 if (*op_end
== ',' && an
!= 0)
317 as_bad ("expected expresssion");
319 op_end
= parse_exp_save_ilp (op_end
, &arg
);
321 fix_new_exp (frag_now
,
322 output
- frag_now
->fr_literal
+ idx
,
323 ASIZE (opcode
->arg
[an
]),
325 PCREL (opcode
->arg
[an
]),
326 pending_reloc
? pending_reloc
: c_to_r (opcode
->arg
[an
]));
328 idx
+= ASIZE (opcode
->arg
[an
]);
332 while (ISSPACE (*op_end
))
336 as_warn ("extra stuff on line ignored");
341 as_bad ("Something forgot to clean up\n");
345 /* Turn a string in input_line_pointer into a floating point constant
346 of type type, and store the appropriate bytes in *LITP. The number
347 of LITTLENUMS emitted is stored in *SIZEP . An error message is
348 returned, or NULL on OK. */
351 md_atof (type
, litP
, sizeP
)
357 LITTLENUM_TYPE words
[4];
373 return _("bad call to md_atof");
376 t
= atof_ieee (input_line_pointer
, type
, words
);
378 input_line_pointer
= t
;
382 if (!target_big_endian
)
384 for (i
= prec
- 1; i
>= 0; i
--)
386 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
392 for (i
= 0; i
< prec
; i
++)
394 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
402 const char *md_shortopts
= "";
404 struct option md_longopts
[] = {
406 #define OPTION_LITTLE (OPTION_MD_BASE)
407 #define OPTION_BIG (OPTION_LITTLE + 1)
409 {"little", no_argument
, NULL
, OPTION_LITTLE
},
410 {"big", no_argument
, NULL
, OPTION_BIG
},
411 {NULL
, no_argument
, NULL
, 0}
413 size_t md_longopts_size
= sizeof (md_longopts
);
416 md_parse_option (c
, arg
)
418 char *arg ATTRIBUTE_UNUSED
;
435 md_show_usage (stream
)
438 fprintf (stream
, _("\
440 -little generate little endian code\n\
441 -big generate big endian code\n"));
444 /* Apply a fixup to the object file. */
447 md_apply_fix3 (fixP
, valP
, seg
)
450 segT seg ATTRIBUTE_UNUSED
;
452 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
459 switch (fixP
->fx_r_type
)
461 case BFD_RELOC_VTABLE_INHERIT
:
462 case BFD_RELOC_VTABLE_ENTRY
:
466 case BFD_RELOC_PJ_CODE_REL16
:
467 if (val
< -0x8000 || val
>= 0x7fff)
468 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("pcrel too far"));
469 buf
[0] |= (val
>> 8) & 0xff;
473 case BFD_RELOC_PJ_CODE_HI16
:
476 fixP
->fx_addnumber
= val
& 0xffff;
479 case BFD_RELOC_PJ_CODE_DIR16
:
480 case BFD_RELOC_PJ_CODE_LO16
:
494 case BFD_RELOC_PJ_CODE_DIR32
:
502 if (target_big_endian
)
519 if (target_big_endian
)
535 if (max
!= 0 && (val
< min
|| val
> max
))
536 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
538 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
542 /* Put number into target byte order. Always put values in an
543 executable section into big endian order. */
546 md_number_to_chars (ptr
, use
, nbytes
)
551 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
552 number_to_chars_bigendian (ptr
, use
, nbytes
);
554 number_to_chars_littleendian (ptr
, use
, nbytes
);
557 /* Translate internal representation of relocation info to BFD target
561 tc_gen_reloc (section
, fixp
)
562 asection
*section ATTRIBUTE_UNUSED
;
566 bfd_reloc_code_real_type r_type
;
568 rel
= (arelent
*) xmalloc (sizeof (arelent
));
569 rel
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
570 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
571 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
573 r_type
= fixp
->fx_r_type
;
574 rel
->addend
= fixp
->fx_addnumber
;
575 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
577 if (rel
->howto
== NULL
)
579 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
580 _("Cannot represent relocation type %s"),
581 bfd_get_reloc_code_name (r_type
));
582 /* Set howto to a garbage value so that we can keep going. */
583 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_32
);
584 assert (rel
->howto
!= NULL
);