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"
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
;
40 int ignore ATTRIBUTE_UNUSED
;
42 target_big_endian
= 0;
47 int ignore ATTRIBUTE_UNUSED
;
49 target_big_endian
= 1;
53 const pseudo_typeS md_pseudo_table
[] = {
60 const char FLT_CHARS
[] = "rRsSfFdDxXpP";
61 const char EXP_CHARS
[] = "eE";
67 if (strncmp (input_line_pointer
, "%hi16", 5) == 0)
70 as_bad (_ ("confusing relocation expressions"));
71 pending_reloc
= BFD_RELOC_PJ_CODE_HI16
;
72 input_line_pointer
+= 5;
75 if (strncmp (input_line_pointer
, "%lo16", 5) == 0)
78 as_bad (_ ("confusing relocation expressions"));
79 pending_reloc
= BFD_RELOC_PJ_CODE_LO16
;
80 input_line_pointer
+= 5;
85 /* Parse an expression and then restore the input line pointer. */
88 parse_exp_save_ilp (s
, op
)
92 char *save
= input_line_pointer
;
93 input_line_pointer
= s
;
95 s
= input_line_pointer
;
96 input_line_pointer
= save
;
100 /* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
101 reloc for a cons. We could use the definition there, except that
102 we want to handle magic pending reloc expressions specially. */
105 pj_cons_fix_new_pj (frag
, where
, nbytes
, exp
)
111 static int rv
[5][2] =
113 { BFD_RELOC_8
, BFD_RELOC_8
},
114 { BFD_RELOC_PJ_CODE_DIR16
, BFD_RELOC_16
},
116 { BFD_RELOC_PJ_CODE_DIR32
, BFD_RELOC_32
}};
118 fix_new_exp (frag
, where
, nbytes
, exp
, 0,
119 pending_reloc
? pending_reloc
120 : rv
[nbytes
][(now_seg
->flags
& SEC_CODE
) ? 0 : 1]);
126 /* Turn a reloc description character from the pj-opc.h table into
127 code which BFD can handle. */
136 return BFD_RELOC_8_PCREL
;
141 return BFD_RELOC_PJ_CODE_REL16
;
144 return BFD_RELOC_PJ_CODE_DIR16
;
146 return BFD_RELOC_PJ_CODE_REL32
;
148 return BFD_RELOC_PJ_CODE_DIR32
;
157 /* Handler for the ipush fake opcode,
158 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
161 ipush_code (opcode
, str
)
162 pj_opc_info_t
*opcode ATTRIBUTE_UNUSED
;
166 char *b
= frag_more (6);
170 parse_exp_save_ilp (str
+ 1, &arg
, &mod
);
172 as_bad (_ ("can't have relocation for ipush"));
175 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 1, 2,
176 &arg
, 0, BFD_RELOC_PJ_CODE_DIR16
);
177 fix_new_exp (frag_now
, b
- frag_now
->fr_literal
+ 4, 2,
178 &arg
, 0, BFD_RELOC_PJ_CODE_HI16
);
181 /* Insert names into the opcode table which are really mini macros,
182 not opcodes. The fakeness is inidicated with an opcode of -1. */
185 fake_opcode (name
, func
) const char *
189 pj_opc_info_t
*fake
= (pj_opc_info_t
*) xmalloc (sizeof (pj_opc_info_t
));
192 fake
->opcode_next
= -1;
193 fake
->name
= (const char *) func
;
194 hash_insert (opcode_hash_control
, name
, (char *) fake
);
198 /* Enter another entry into the opcode hash table so the same opcode
199 can have another name. */
201 alias (new, old
) const char *
205 hash_insert (opcode_hash_control
, new,
206 (char *) hash_find (opcode_hash_control
, old
));
210 /* This function is called once, at assembler startup time. It sets
211 up the hash table with all the opcodes in it, and also initializes
212 some aliases for compatibility with other assemblers. */
217 const pj_opc_info_t
*opcode
;
218 opcode_hash_control
= hash_new ();
220 /* Insert names into hash table */
221 for (opcode
= pj_opc_info
; opcode
->name
; opcode
++)
222 hash_insert (opcode_hash_control
, opcode
->name
, (char *) opcode
);
224 /* Insert the only fake opcode. */
225 fake_opcode ("ipush", ipush_code
);
227 /* Add some aliases for opcode names. */
228 alias ("ifeq_s", "ifeq");
229 alias ("ifne_s", "ifne");
230 alias ("if_icmpge_s", "if_icmpge");
231 alias ("if_icmpne_s", "if_icmpne");
232 alias ("if_icmpeq_s", "if_icmpeq");
233 alias ("if_icmpgt_s", "if_icmpgt");
234 alias ("goto_s", "goto");
236 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, 0);
239 /* This is the guts of the machine-dependent assembler. STR points to a
240 machine dependent instruction. This function is supposed to emit
241 the frags/bytes it assembles to.
248 unsigned char *op_start
;
249 unsigned char *op_end
;
251 // pj_operan_info operand[3];
252 pj_opc_info_t
*opcode
;
259 /* Drop leading whitespace */
263 /* find the op code end */
264 for (op_start
= op_end
= (unsigned char *) (str
);
265 *op_end
&& !is_end_of_line
[*op_end
] && *op_end
!= ' ';
274 as_bad (_ ("can't find opcode "));
277 opcode
= (pj_opc_info_t
*) hash_find (opcode_hash_control
, op_start
);
282 as_bad (_ ("unknown opcode %s"), op_start
);
286 if (opcode
->opcode
== -1)
288 /* It's a fake opcode.. dig out the args and pretend that was
289 what we were passed */
290 ((void (*)()) opcode
->name
) (opcode
, op_end
);
296 output
= frag_more (opcode
->len
);
297 output
[idx
++] = opcode
->opcode
;
299 if (opcode
->opcode_next
!= -1)
300 output
[idx
++] = opcode
->opcode_next
;
302 for (an
= 0; opcode
->arg
[an
]; an
++)
306 if (*op_end
== ',' && an
!= 0)
310 as_bad ("expected expresssion");
312 op_end
= parse_exp_save_ilp (op_end
, &arg
);
314 fix_new_exp (frag_now
,
315 output
- frag_now
->fr_literal
+ idx
,
316 ASIZE (opcode
->arg
[an
]),
318 PCREL (opcode
->arg
[an
]),
319 pending_reloc
? pending_reloc
: c_to_r (opcode
->arg
[an
]));
321 idx
+= ASIZE (opcode
->arg
[an
]);
325 while (isspace (*op_end
))
329 as_warn ("extra stuff on line ignored");
334 as_bad ("Something forgot to clean up\n");
338 /* Turn a string in input_line_pointer into a floating point constant of type
339 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
340 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
343 md_atof (type
, litP
, sizeP
)
349 LITTLENUM_TYPE words
[4];
365 return _ ("bad call to md_atof");
368 t
= atof_ieee (input_line_pointer
, type
, words
);
370 input_line_pointer
= t
;
374 if (!target_big_endian
)
376 for (i
= prec
- 1; i
>= 0; i
--)
378 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
384 for (i
= 0; i
< prec
; i
++)
386 md_number_to_chars (litP
, (valueT
) words
[i
], 2);
395 CONST
char *md_shortopts
= "";
397 struct option md_longopts
[] = {
399 #define OPTION_LITTLE (OPTION_MD_BASE)
400 #define OPTION_BIG (OPTION_LITTLE + 1)
402 {"little", no_argument
, NULL
, OPTION_LITTLE
},
403 {"big", no_argument
, NULL
, OPTION_BIG
},
404 {NULL
, no_argument
, NULL
, 0}
406 size_t md_longopts_size
= sizeof (md_longopts
);
409 md_parse_option (c
, arg
)
411 char *arg ATTRIBUTE_UNUSED
;
428 md_show_usage (stream
)
431 fprintf (stream
, _ ("\
433 -little generate little endian code\n\
434 -big generate big endian code\n"));
439 /* Apply a fixup to the object file. */
443 md_apply_fix (fixP
, valp
)
447 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
453 /* adjust_reloc_syms won't convert a reloc against a weak symbol
454 into a reloc against a section, but bfd_install_relocation will
455 screw up if the symbol is defined, so we have to adjust val here
456 to avoid the screw up later. */
458 if (fixP
->fx_addsy
!= NULL
&& S_IS_WEAK (fixP
->fx_addsy
))
459 val
-= S_GET_VALUE (fixP
->fx_addsy
);
463 switch (fixP
->fx_r_type
)
465 case BFD_RELOC_VTABLE_INHERIT
:
466 case BFD_RELOC_VTABLE_ENTRY
:
470 case BFD_RELOC_PJ_CODE_REL16
:
471 if (val
< -0x8000 || val
>= 0x7fff)
472 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _ ("pcrel too far"));
473 buf
[0] |= (val
>> 8) & 0xff;
477 case BFD_RELOC_PJ_CODE_HI16
:
480 fixP
->fx_addnumber
= val
& 0xffff;
483 case BFD_RELOC_PJ_CODE_DIR16
:
484 case BFD_RELOC_PJ_CODE_LO16
:
498 case BFD_RELOC_PJ_CODE_DIR32
:
506 if (target_big_endian
)
523 if (target_big_endian
)
540 if (max
!= 0 && (val
< min
|| val
> max
))
541 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _ ("offset out of range"));
546 /* Put number into target byte order. Always put values in an
547 executable section into big endian order. */
550 md_number_to_chars (ptr
, use
, nbytes
)
555 if (target_big_endian
|| now_seg
->flags
& SEC_CODE
)
556 number_to_chars_bigendian (ptr
, use
, nbytes
);
558 number_to_chars_littleendian (ptr
, use
, nbytes
);
563 /* Translate internal representation of relocation info to BFD target
567 tc_gen_reloc (section
, fixp
)
568 asection
*section ATTRIBUTE_UNUSED
;
572 bfd_reloc_code_real_type r_type
;
574 rel
= (arelent
*) xmalloc (sizeof (arelent
));
575 rel
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
576 *rel
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
577 rel
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
579 r_type
= fixp
->fx_r_type
;
580 rel
->addend
= fixp
->fx_addnumber
;
581 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, r_type
);
583 if (rel
->howto
== NULL
)
585 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
586 _ ("Cannot represent relocation type %s"),
587 bfd_get_reloc_code_name (r_type
));
588 /* Set howto to a garbage value so that we can keep going. */
589 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, BFD_RELOC_32
);
590 assert (rel
->howto
!= NULL
);