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, 51 Franklin Street - Fifth Floor,
21 Boston, MA 02110-1301, 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
;
39 little (int ignore ATTRIBUTE_UNUSED
)
41 target_big_endian
= 0;
45 big (int ignore ATTRIBUTE_UNUSED
)
47 target_big_endian
= 1;
50 const pseudo_typeS md_pseudo_table
[] =
57 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
58 const char EXP_CHARS
[] = "eE";
61 md_operand (expressionS
*op
)
63 if (strncmp (input_line_pointer
, "%hi16", 5) == 0)
66 as_bad (_("confusing relocation expressions"));
67 pending_reloc
= BFD_RELOC_PJ_CODE_HI16
;
68 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 (char *s
, expressionS
*op
)
87 char *save
= input_line_pointer
;
89 input_line_pointer
= s
;
91 s
= input_line_pointer
;
92 input_line_pointer
= save
;
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. */
101 pj_cons_fix_new_pj (fragS
*frag
, int where
, int nbytes
, expressionS
*exp
)
103 static int rv
[5][2] =
105 { BFD_RELOC_8
, BFD_RELOC_8
},
106 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
108 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
110 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
111 pending_reloc
? pending_reloc
112 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
117 /* Turn a reloc description character from the pj-opc.h table into
118 code which BFD can handle. */
126 return BFD_RELOC_8_PCREL
;
131 return BFD_RELOC_PJ_CODE_REL16
;
134 return BFD_RELOC_PJ_CODE_DIR16
;
136 return BFD_RELOC_PJ_CODE_REL32
;
138 return BFD_RELOC_PJ_CODE_DIR32
;
144 /* Handler for the ipush fake opcode,
145 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
148 ipush_code (pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
, char *str
)
150 char *b
= frag_more (6);
155 parse_exp_save_ilp (str
+ 1, &arg
);
158 as_bad (_("can't have relocation for ipush"));
162 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
163 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
164 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
165 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
168 /* Insert names into the opcode table which are really mini macros,
169 not opcodes. The fakeness is indicated with an opcode of -1. */
172 fake_opcode (const char *name
,
173 void (*func
) (struct pj_opc_info_t
*, char *))
175 pj_opc_info_t
* fake
= xmalloc (sizeof (pj_opc_info_t
));
178 fake
->opcode_next
= -1;
180 hash_insert (opcode_hash_control
, name
, (char *) fake
);
183 /* Enter another entry into the opcode hash table so the same opcode
184 can have another name. */
187 alias (const char *new, const char *old
)
189 hash_insert (opcode_hash_control
, new,
190 (char *) hash_find (opcode_hash_control
, old
));
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
195 some aliases for compatibility with other assemblers. */
200 const pj_opc_info_t
*opcode
;
201 opcode_hash_control
= hash_new ();
203 /* Insert names into hash table. */
204 for (opcode
= pj_opc_info
; opcode
->u
.name
; opcode
++)
205 hash_insert (opcode_hash_control
, opcode
->u
.name
, (char *) opcode
);
207 /* Insert the only fake opcode. */
208 fake_opcode ("ipush", ipush_code
);
210 /* Add some aliases for opcode names. */
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");
219 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
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. */
227 md_assemble (char *str
)
232 pj_opc_info_t
*opcode
;
239 /* Drop leading whitespace. */
243 /* Find the op code end. */
246 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
254 as_bad (_("can't find opcode "));
256 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
261 as_bad (_("unknown opcode %s"), op_start
);
265 if (opcode
->opcode
== -1)
267 /* It's a fake opcode. Dig out the args and pretend that was
268 what we were passed. */
269 (*opcode
->u
.func
) (opcode
, op_end
);
275 output
= frag_more (opcode
->len
);
276 output
[idx
++] = opcode
->opcode
;
278 if (opcode
->opcode_next
!= -1)
279 output
[idx
++] = opcode
->opcode_next
;
281 for (an
= 0; opcode
->arg
[an
]; an
++)
285 if (*op_end
== ',' && an
!= 0)
289 as_bad ("expected expresssion");
291 op_end
= parse_exp_save_ilp (op_end
, &arg
);
293 fix_new_exp (frag_now
,
294 output
- frag_now
->fr_literal
+ idx
,
295 ASIZE (opcode
->arg
[an
]),
297 PCREL (opcode
->arg
[an
]),
298 pending_reloc
? pending_reloc
: c_to_r (opcode
->arg
[an
]));
300 idx
+= ASIZE (opcode
->arg
[an
]);
304 while (ISSPACE (*op_end
))
308 as_warn ("extra stuff on line ignored");
313 as_bad ("Something forgot to clean up\n");
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. */
323 md_atof (int type
, char *litP
, int *sizeP
)
326 LITTLENUM_TYPE words
[4];
342 return _("bad call to md_atof");
345 t
= atof_ieee (input_line_pointer
, type
, words
);
347 input_line_pointer
= t
;
351 if (!target_big_endian
)
353 for (i
= prec
- 1; i
>= 0; i
--)
355 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
361 for (i
= 0; i
< prec
; i
++)
363 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
371 const char *md_shortopts
= "";
373 struct option md_longopts
[] =
375 #define OPTION_LITTLE (OPTION_MD_BASE)
376 #define OPTION_BIG (OPTION_LITTLE + 1)
378 {"little", no_argument
, NULL
, OPTION_LITTLE
},
379 {"big", no_argument
, NULL
, OPTION_BIG
},
380 {NULL
, no_argument
, NULL
, 0}
382 size_t md_longopts_size
= sizeof (md_longopts
);
385 md_parse_option (int c
, char *arg ATTRIBUTE_UNUSED
)
402 md_show_usage (FILE *stream
)
404 fprintf (stream
, _("\
406 -little generate little endian code\n\
407 -big generate big endian code\n"));
410 /* Apply a fixup to the object file. */
413 md_apply_fix3 (fixS
*fixP
, valueT
* valP
, segT seg ATTRIBUTE_UNUSED
)
415 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
422 switch (fixP
->fx_r_type
)
424 case BFD_RELOC_VTABLE_INHERIT
:
425 case BFD_RELOC_VTABLE_ENTRY
:
429 case BFD_RELOC_PJ_CODE_REL16
:
430 if (val
< -0x8000 || val
>= 0x7fff)
431 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("pcrel too far"));
432 buf
[0] |= (val
>> 8) & 0xff;
436 case BFD_RELOC_PJ_CODE_HI16
:
439 fixP
->fx_addnumber
= val
& 0xffff;
442 case BFD_RELOC_PJ_CODE_DIR16
:
443 case BFD_RELOC_PJ_CODE_LO16
:
457 case BFD_RELOC_PJ_CODE_DIR32
:
465 if (target_big_endian
)
482 if (target_big_endian
)
498 if (max
!= 0 && (val
< min
|| val
> max
))
499 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
501 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
505 /* Put number into target byte order. Always put values in an
506 executable section into big endian order. */
509 md_number_to_chars (char *ptr
, valueT use
, int nbytes
)
511 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
512 number_to_chars_bigendian (ptr
, use
, nbytes
);
514 number_to_chars_littleendian (ptr
, use
, nbytes
);
517 /* Translate internal representation of relocation info to BFD target
521 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixp
)
524 bfd_reloc_code_real_type r_type
;
526 rel
= xmalloc (sizeof (arelent
));
527 rel
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
528 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
529 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
531 r_type
= fixp
->fx_r_type
;
532 rel
->addend
= fixp
->fx_addnumber
;
533 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
535 if (rel
->howto
== NULL
)
537 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
538 _("Cannot represent relocation type %s"),
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
);