2 tc-pj.c -- Assemble code for Pico Java
3 Copyright (C) 1999 Free Software Foundation.
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 "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
;
38 int ignore ATTRIBUTE_UNUSED
;
40 target_big_endian
= 0;
45 int ignore ATTRIBUTE_UNUSED
;
47 target_big_endian
= 1;
50 const pseudo_typeS md_pseudo_table
[] = {
56 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
57 const char EXP_CHARS
[] = "eE";
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;
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 (s
, op
)
88 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 (frag
, where
, nbytes
, exp
)
107 static int rv
[5][2] =
109 { BFD_RELOC_8
, BFD_RELOC_8
},
110 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
112 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
114 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
115 pending_reloc
? pending_reloc
116 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
121 /* Turn a reloc description character from the pj-opc.h table into
122 code which BFD can handle. */
131 return BFD_RELOC_8_PCREL
;
136 return BFD_RELOC_PJ_CODE_REL16
;
139 return BFD_RELOC_PJ_CODE_DIR16
;
141 return BFD_RELOC_PJ_CODE_REL32
;
143 return BFD_RELOC_PJ_CODE_DIR32
;
149 /* Handler for the ipush fake opcode,
150 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
153 ipush_code (opcode
, str
)
154 pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
;
158 char *b
= frag_more (6);
163 parse_exp_save_ilp (str
+ 1, &arg
, &mod
);
165 as_bad (_("can't have relocation for ipush"));
167 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
168 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
169 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
170 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
173 /* Insert names into the opcode table which are really mini macros,
174 not opcodes. The fakeness is inidicated with an opcode of -1. */
177 fake_opcode (name
, func
)
181 pj_opc_info_t
*fake
= (pj_opc_info_t
*) xmalloc (sizeof (pj_opc_info_t
));
184 fake
->opcode_next
= -1;
185 fake
->name
= (const char *) func
;
186 hash_insert (opcode_hash_control
, name
, (char *) fake
);
189 /* Enter another entry into the opcode hash table so the same opcode
190 can have another name. */
197 hash_insert (opcode_hash_control
, new,
198 (char *) hash_find (opcode_hash_control
, old
));
201 /* This function is called once, at assembler startup time. It sets
202 up the hash table with all the opcodes in it, and also initializes
203 some aliases for compatibility with other assemblers. */
208 const pj_opc_info_t
*opcode
;
209 opcode_hash_control
= hash_new ();
211 /* Insert names into hash table. */
212 for (opcode
= pj_opc_info
; opcode
->name
; opcode
++)
213 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
215 /* Insert the only fake opcode. */
216 fake_opcode ("ipush", ipush_code
);
218 /* Add some aliases for opcode names. */
219 alias ("ifeq_s", "ifeq");
220 alias ("ifne_s", "ifne");
221 alias ("if_icmpge_s", "if_icmpge");
222 alias ("if_icmpne_s", "if_icmpne");
223 alias ("if_icmpeq_s", "if_icmpeq");
224 alias ("if_icmpgt_s", "if_icmpgt");
225 alias ("goto_s", "goto");
227 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
230 /* This is the guts of the machine-dependent assembler. STR points to
231 a machine dependent instruction. This function is supposed to emit
232 the frags/bytes it assembles to. */
238 unsigned char *op_start
;
239 unsigned char *op_end
;
242 pj_operan_info operand
[3];
244 pj_opc_info_t
*opcode
;
251 /* Drop leading whitespace. */
255 /* Find the op code end. */
256 for (op_start
= op_end
= (unsigned char *) (str
);
257 *op_end
&& !is_end_of_line
[*op_end
] && *op_end
!= ' ';
265 as_bad (_("can't find opcode "));
267 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
272 as_bad (_("unknown opcode %s"), op_start
);
276 if (opcode
->opcode
== -1)
278 /* It's a fake opcode. Dig out the args and pretend that was
279 what we were passed. */
280 ((void (*) ()) opcode
->name
) (opcode
, op_end
);
286 output
= frag_more (opcode
->len
);
287 output
[idx
++] = opcode
->opcode
;
289 if (opcode
->opcode_next
!= -1)
290 output
[idx
++] = opcode
->opcode_next
;
292 for (an
= 0; opcode
->arg
[an
]; an
++)
296 if (*op_end
== ',' && an
!= 0)
300 as_bad ("expected expresssion");
302 op_end
= parse_exp_save_ilp (op_end
, &arg
);
304 fix_new_exp (frag_now
,
305 output
- frag_now
->fr_literal
+ idx
,
306 ASIZE (opcode
->arg
[an
]),
308 PCREL (opcode
->arg
[an
]),
309 pending_reloc
? pending_reloc
: c_to_r (opcode
->arg
[an
]));
311 idx
+= ASIZE (opcode
->arg
[an
]);
315 while (isspace (*op_end
))
319 as_warn ("extra stuff on line ignored");
324 as_bad ("Something forgot to clean up\n");
328 /* Turn a string in input_line_pointer into a floating point constant
329 of type type, and store the appropriate bytes in *LITP. The number
330 of LITTLENUMS emitted is stored in *SIZEP . An error message is
331 returned, or NULL on OK. */
334 md_atof (type
, litP
, sizeP
)
340 LITTLENUM_TYPE words
[4];
356 return _("bad call to md_atof");
359 t
= atof_ieee (input_line_pointer
, type
, words
);
361 input_line_pointer
= t
;
365 if (!target_big_endian
)
367 for (i
= prec
- 1; i
>= 0; i
--)
369 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
375 for (i
= 0; i
< prec
; i
++)
377 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
385 CONST
char *md_shortopts
= "";
387 struct option md_longopts
[] = {
389 #define OPTION_LITTLE (OPTION_MD_BASE)
390 #define OPTION_BIG (OPTION_LITTLE + 1)
392 {"little", no_argument
, NULL
, OPTION_LITTLE
},
393 {"big", no_argument
, NULL
, OPTION_BIG
},
394 {NULL
, no_argument
, NULL
, 0}
396 size_t md_longopts_size
= sizeof (md_longopts
);
399 md_parse_option (c
, arg
)
401 char *arg ATTRIBUTE_UNUSED
;
418 md_show_usage (stream
)
421 fprintf (stream
, _("\
423 -little generate little endian code\n\
424 -big generate big endian code\n"));
427 /* Apply a fixup to the object file. */
430 md_apply_fix (fixP
, valp
)
434 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
439 /* adjust_reloc_syms won't convert a reloc against a weak symbol
440 into a reloc against a section, but bfd_install_relocation will
441 screw up if the symbol is defined, so we have to adjust val here
442 to avoid the screw up later. */
444 if (fixP
->fx_addsy
!= NULL
&& S_IS_WEAK (fixP
->fx_addsy
))
445 val
-= S_GET_VALUE (fixP
->fx_addsy
);
449 switch (fixP
->fx_r_type
)
451 case BFD_RELOC_VTABLE_INHERIT
:
452 case BFD_RELOC_VTABLE_ENTRY
:
456 case BFD_RELOC_PJ_CODE_REL16
:
457 if (val
< -0x8000 || val
>= 0x7fff)
458 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("pcrel too far"));
459 buf
[0] |= (val
>> 8) & 0xff;
463 case BFD_RELOC_PJ_CODE_HI16
:
466 fixP
->fx_addnumber
= val
& 0xffff;
469 case BFD_RELOC_PJ_CODE_DIR16
:
470 case BFD_RELOC_PJ_CODE_LO16
:
484 case BFD_RELOC_PJ_CODE_DIR32
:
492 if (target_big_endian
)
509 if (target_big_endian
)
525 if (max
!= 0 && (val
< min
|| val
> max
))
526 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("offset out of range"));
531 /* Put number into target byte order. Always put values in an
532 executable section into big endian order. */
535 md_number_to_chars (ptr
, use
, nbytes
)
540 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
541 number_to_chars_bigendian (ptr
, use
, nbytes
);
543 number_to_chars_littleendian (ptr
, use
, nbytes
);
546 /* Translate internal representation of relocation info to BFD target
550 tc_gen_reloc (section
, fixp
)
551 asection
*section ATTRIBUTE_UNUSED
;
555 bfd_reloc_code_real_type r_type
;
557 rel
= (arelent
*) xmalloc (sizeof (arelent
));
558 rel
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
559 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
560 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
562 r_type
= fixp
->fx_r_type
;
563 rel
->addend
= fixp
->fx_addnumber
;
564 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
566 if (rel
->howto
== NULL
)
568 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
569 _("Cannot represent relocation type %s"),
570 bfd_get_reloc_code_name (r_type
));
571 /* Set howto to a garbage value so that we can keep going. */
572 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_32
);
573 assert (rel
->howto
!= NULL
);