1 /* tc-pj.c -- Assemble code for Pico Java
2 Copyright (C) 1999-2014 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
21 /* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
24 #include "safe-ctype.h"
25 #include "opcode/pj.h"
27 extern const pj_opc_info_t pj_opc_info
[512];
29 const char comment_chars
[] = "!/";
30 const char line_separator_chars
[] = ";";
31 const char line_comment_chars
[] = "/!#";
33 static int pending_reloc
;
34 static struct hash_control
*opcode_hash_control
;
37 little (int ignore ATTRIBUTE_UNUSED
)
39 target_big_endian
= 0;
43 big (int ignore ATTRIBUTE_UNUSED
)
45 target_big_endian
= 1;
48 const pseudo_typeS md_pseudo_table
[] =
55 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
56 const char EXP_CHARS
[] = "eE";
59 md_operand (expressionS
*op
)
61 if (strncmp (input_line_pointer
, "%hi16", 5) == 0)
64 as_bad (_("confusing relocation expressions"));
65 pending_reloc
= BFD_RELOC_PJ_CODE_HI16
;
66 input_line_pointer
+= 5;
70 if (strncmp (input_line_pointer
, "%lo16", 5) == 0)
73 as_bad (_("confusing relocation expressions"));
74 pending_reloc
= BFD_RELOC_PJ_CODE_LO16
;
75 input_line_pointer
+= 5;
80 /* Parse an expression and then restore the input line pointer. */
83 parse_exp_save_ilp (char *s
, expressionS
*op
)
85 char *save
= input_line_pointer
;
87 input_line_pointer
= s
;
89 s
= input_line_pointer
;
90 input_line_pointer
= save
;
94 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
95 reloc for a cons. We could use the definition there, except that
96 we want to handle magic pending reloc expressions specially. */
99 pj_cons_fix_new_pj (fragS
*frag
, int where
, int nbytes
, expressionS
*exp
)
101 static int rv
[5][2] =
103 { BFD_RELOC_8
, BFD_RELOC_8
},
104 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
106 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
108 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
109 pending_reloc
? pending_reloc
110 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
115 /* Turn a reloc description character from the pj-opc.h table into
116 code which BFD can handle. */
124 return BFD_RELOC_8_PCREL
;
129 return BFD_RELOC_PJ_CODE_REL16
;
132 return BFD_RELOC_PJ_CODE_DIR16
;
134 return BFD_RELOC_PJ_CODE_REL32
;
136 return BFD_RELOC_PJ_CODE_DIR32
;
142 /* Handler for the ipush fake opcode,
143 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
146 ipush_code (pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
, char *str
)
148 char *b
= frag_more (6);
153 parse_exp_save_ilp (str
+ 1, &arg
);
156 as_bad (_("can't have relocation for ipush"));
160 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
161 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
162 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
163 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
166 /* Insert names into the opcode table which are really mini macros,
167 not opcodes. The fakeness is indicated with an opcode of -1. */
170 fake_opcode (const char *name
,
171 void (*func
) (struct pj_opc_info_t
*, char *))
173 pj_opc_info_t
* fake
= xmalloc (sizeof (pj_opc_info_t
));
176 fake
->opcode_next
= -1;
178 hash_insert (opcode_hash_control
, name
, (char *) fake
);
181 /* Enter another entry into the opcode hash table so the same opcode
182 can have another name. */
185 alias (const char *new_name
, const char *old
)
187 hash_insert (opcode_hash_control
, new_name
,
188 (char *) hash_find (opcode_hash_control
, old
));
191 /* This function is called once, at assembler startup time. It sets
192 up the hash table with all the opcodes in it, and also initializes
193 some aliases for compatibility with other assemblers. */
198 const pj_opc_info_t
*opcode
;
199 opcode_hash_control
= hash_new ();
201 /* Insert names into hash table. */
202 for (opcode
= pj_opc_info
; opcode
->u
.name
; opcode
++)
203 hash_insert (opcode_hash_control
, opcode
->u
.name
, (char *) opcode
);
205 /* Insert the only fake opcode. */
206 fake_opcode ("ipush", ipush_code
);
208 /* Add some aliases for opcode names. */
209 alias ("ifeq_s", "ifeq");
210 alias ("ifne_s", "ifne");
211 alias ("if_icmpge_s", "if_icmpge");
212 alias ("if_icmpne_s", "if_icmpne");
213 alias ("if_icmpeq_s", "if_icmpeq");
214 alias ("if_icmpgt_s", "if_icmpgt");
215 alias ("goto_s", "goto");
217 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
220 /* This is the guts of the machine-dependent assembler. STR points to
221 a machine dependent instruction. This function is supposed to emit
222 the frags/bytes it assembles to. */
225 md_assemble (char *str
)
230 pj_opc_info_t
*opcode
;
237 /* Drop leading whitespace. */
241 /* Find the op code end. */
244 *op_end
&& !is_end_of_line
[*op_end
& 0xff] && *op_end
!= ' ';
252 as_bad (_("can't find opcode "));
254 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
259 as_bad (_("unknown opcode %s"), op_start
);
263 dwarf2_emit_insn (0);
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 expression"));
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
;
370 switch (fixP
->fx_r_type
)
372 case BFD_RELOC_VTABLE_INHERIT
:
373 case BFD_RELOC_VTABLE_ENTRY
:
377 case BFD_RELOC_PJ_CODE_REL16
:
378 if (val
< -0x8000 || val
>= 0x7fff)
379 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("pcrel too far"));
380 buf
[0] |= (val
>> 8) & 0xff;
384 case BFD_RELOC_PJ_CODE_HI16
:
387 fixP
->fx_addnumber
= val
& 0xffff;
390 case BFD_RELOC_PJ_CODE_DIR16
:
391 case BFD_RELOC_PJ_CODE_LO16
:
405 case BFD_RELOC_PJ_CODE_DIR32
:
413 if (target_big_endian
)
430 if (target_big_endian
)
446 if (max
!= 0 && (val
< min
|| val
> max
))
447 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
449 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
453 /* Put number into target byte order. Always put values in an
454 executable section into big endian order. */
457 md_number_to_chars (char *ptr
, valueT use
, int nbytes
)
459 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
460 number_to_chars_bigendian (ptr
, use
, nbytes
);
462 number_to_chars_littleendian (ptr
, use
, nbytes
);
465 /* Translate internal representation of relocation info to BFD target
469 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixp
)
472 bfd_reloc_code_real_type r_type
;
474 rel
= xmalloc (sizeof (arelent
));
475 rel
->sym_ptr_ptr
= xmalloc (sizeof (asymbol
*));
476 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
477 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
479 r_type
= fixp
->fx_r_type
;
480 rel
->addend
= fixp
->fx_addnumber
;
481 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
483 if (rel
->howto
== NULL
)
485 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
486 _("Cannot represent relocation type %s"),
487 bfd_get_reloc_code_name (r_type
));
488 /* Set howto to a garbage value so that we can keep going. */
489 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_32
);
490 gas_assert (rel
->howto
!= NULL
);