1 /* tc-pj.c -- Assemble code for Pico Java
2 Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007
3 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 3, 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, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, 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
;
38 little (int ignore ATTRIBUTE_UNUSED
)
40 target_big_endian
= 0;
44 big (int ignore ATTRIBUTE_UNUSED
)
46 target_big_endian
= 1;
49 const pseudo_typeS md_pseudo_table
[] =
56 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
57 const char EXP_CHARS
[] = "eE";
60 md_operand (expressionS
*op
)
62 if (strncmp (input_line_pointer
, "%hi16", 5) == 0)
65 as_bad (_("confusing relocation expressions"));
66 pending_reloc
= BFD_RELOC_PJ_CODE_HI16
;
67 input_line_pointer
+= 5;
71 if (strncmp (input_line_pointer
, "%lo16", 5) == 0)
74 as_bad (_("confusing relocation expressions"));
75 pending_reloc
= BFD_RELOC_PJ_CODE_LO16
;
76 input_line_pointer
+= 5;
81 /* Parse an expression and then restore the input line pointer. */
84 parse_exp_save_ilp (char *s
, expressionS
*op
)
86 char *save
= input_line_pointer
;
88 input_line_pointer
= s
;
90 s
= input_line_pointer
;
91 input_line_pointer
= save
;
95 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
96 reloc for a cons. We could use the definition there, except that
97 we want to handle magic pending reloc expressions specially. */
100 pj_cons_fix_new_pj (fragS
*frag
, int where
, int nbytes
, expressionS
*exp
)
102 static int rv
[5][2] =
104 { BFD_RELOC_8
, BFD_RELOC_8
},
105 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
107 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
109 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
110 pending_reloc
? pending_reloc
111 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
116 /* Turn a reloc description character from the pj-opc.h table into
117 code which BFD can handle. */
125 return BFD_RELOC_8_PCREL
;
130 return BFD_RELOC_PJ_CODE_REL16
;
133 return BFD_RELOC_PJ_CODE_DIR16
;
135 return BFD_RELOC_PJ_CODE_REL32
;
137 return BFD_RELOC_PJ_CODE_DIR32
;
143 /* Handler for the ipush fake opcode,
144 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
147 ipush_code (pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
, char *str
)
149 char *b
= frag_more (6);
154 parse_exp_save_ilp (str
+ 1, &arg
);
157 as_bad (_("can't have relocation for ipush"));
161 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
162 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
163 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
164 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
167 /* Insert names into the opcode table which are really mini macros,
168 not opcodes. The fakeness is indicated with an opcode of -1. */
171 fake_opcode (const char *name
,
172 void (*func
) (struct pj_opc_info_t
*, char *))
174 pj_opc_info_t
* fake
= xmalloc (sizeof (pj_opc_info_t
));
177 fake
->opcode_next
= -1;
179 hash_insert (opcode_hash_control
, name
, (char *) fake
);
182 /* Enter another entry into the opcode hash table so the same opcode
183 can have another name. */
186 alias (const char *new, const char *old
)
188 hash_insert (opcode_hash_control
, new,
189 (char *) hash_find (opcode_hash_control
, old
));
192 /* This function is called once, at assembler startup time. It sets
193 up the hash table with all the opcodes in it, and also initializes
194 some aliases for compatibility with other assemblers. */
199 const pj_opc_info_t
*opcode
;
200 opcode_hash_control
= hash_new ();
202 /* Insert names into hash table. */
203 for (opcode
= pj_opc_info
; opcode
->u
.name
; opcode
++)
204 hash_insert (opcode_hash_control
, opcode
->u
.name
, (char *) opcode
);
206 /* Insert the only fake opcode. */
207 fake_opcode ("ipush", ipush_code
);
209 /* Add some aliases for opcode names. */
210 alias ("ifeq_s", "ifeq");
211 alias ("ifne_s", "ifne");
212 alias ("if_icmpge_s", "if_icmpge");
213 alias ("if_icmpne_s", "if_icmpne");
214 alias ("if_icmpeq_s", "if_icmpeq");
215 alias ("if_icmpgt_s", "if_icmpgt");
216 alias ("goto_s", "goto");
218 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
221 /* This is the guts of the machine-dependent assembler. STR points to
222 a machine dependent instruction. This function is supposed to emit
223 the frags/bytes it assembles to. */
226 md_assemble (char *str
)
231 pj_opc_info_t
*opcode
;
238 /* Drop leading whitespace. */
242 /* Find the op code end. */
245 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
253 as_bad (_("can't find opcode "));
255 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
260 as_bad (_("unknown opcode %s"), op_start
);
264 if (opcode
->opcode
== -1)
266 /* It's a fake opcode. Dig out the args and pretend that was
267 what we were passed. */
268 (*opcode
->u
.func
) (opcode
, op_end
);
274 output
= frag_more (opcode
->len
);
275 output
[idx
++] = opcode
->opcode
;
277 if (opcode
->opcode_next
!= -1)
278 output
[idx
++] = opcode
->opcode_next
;
280 for (an
= 0; opcode
->arg
[an
]; an
++)
284 if (*op_end
== ',' && an
!= 0)
288 as_bad (_("expected expresssion"));
290 op_end
= parse_exp_save_ilp (op_end
, &arg
);
292 fix_new_exp (frag_now
,
293 output
- frag_now
->fr_literal
+ idx
,
294 ASIZE (opcode
->arg
[an
]),
296 PCREL (opcode
->arg
[an
]),
297 pending_reloc
? pending_reloc
: c_to_r (opcode
->arg
[an
]));
299 idx
+= ASIZE (opcode
->arg
[an
]);
303 while (ISSPACE (*op_end
))
307 as_warn (_("extra stuff on line ignored"));
312 as_bad (_("Something forgot to clean up\n"));
316 md_atof (int type
, char *litP
, int *sizeP
)
318 return ieee_md_atof (type
, litP
, sizeP
, target_big_endian
);
321 const char *md_shortopts
= "";
323 struct option md_longopts
[] =
325 #define OPTION_LITTLE (OPTION_MD_BASE)
326 #define OPTION_BIG (OPTION_LITTLE + 1)
328 {"little", no_argument
, NULL
, OPTION_LITTLE
},
329 {"big", no_argument
, NULL
, OPTION_BIG
},
330 {NULL
, no_argument
, NULL
, 0}
332 size_t md_longopts_size
= sizeof (md_longopts
);
335 md_parse_option (int c
, char *arg ATTRIBUTE_UNUSED
)
352 md_show_usage (FILE *stream
)
354 fprintf (stream
, _("\
356 -little generate little endian code\n\
357 -big generate big endian code\n"));
360 /* Apply a fixup to the object file. */
363 md_apply_fix (fixS
*fixP
, valueT
* valP
, segT seg ATTRIBUTE_UNUSED
)
365 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
372 switch (fixP
->fx_r_type
)
374 case BFD_RELOC_VTABLE_INHERIT
:
375 case BFD_RELOC_VTABLE_ENTRY
:
379 case BFD_RELOC_PJ_CODE_REL16
:
380 if (val
< -0x8000 || val
>= 0x7fff)
381 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("pcrel too far"));
382 buf
[0] |= (val
>> 8) & 0xff;
386 case BFD_RELOC_PJ_CODE_HI16
:
389 fixP
->fx_addnumber
= val
& 0xffff;
392 case BFD_RELOC_PJ_CODE_DIR16
:
393 case BFD_RELOC_PJ_CODE_LO16
:
407 case BFD_RELOC_PJ_CODE_DIR32
:
415 if (target_big_endian
)
432 if (target_big_endian
)
448 if (max
!= 0 && (val
< min
|| val
> max
))
449 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
451 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
455 /* Put number into target byte order. Always put values in an
456 executable section into big endian order. */
459 md_number_to_chars (char *ptr
, valueT use
, int nbytes
)
461 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
462 number_to_chars_bigendian (ptr
, use
, nbytes
);
464 number_to_chars_littleendian (ptr
, use
, nbytes
);
467 /* Translate internal representation of relocation info to BFD target
471 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixp
)
474 bfd_reloc_code_real_type r_type
;
476 rel
= xmalloc (sizeof (arelent
));
477 rel
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
478 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
479 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
481 r_type
= fixp
->fx_r_type
;
482 rel
->addend
= fixp
->fx_addnumber
;
483 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
485 if (rel
->howto
== NULL
)
487 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
488 _("Cannot represent relocation type %s"),
489 bfd_get_reloc_code_name (r_type
));
490 /* Set howto to a garbage value so that we can keep going. */
491 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_32
);
492 gas_assert (rel
->howto
!= NULL
);