update copyright dates
[deliverable/binutils-gdb.git] / gas / config / tc-pj.c
CommitLineData
ec2655a6 1/* tc-pj.c -- Assemble code for Pico Java
aa820537 2 Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2009
aef6203b 3 Free Software Foundation, Inc.
041dd5a9
ILT
4
5 This file is part of GAS, the GNU Assembler.
6
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
ec2655a6 9 the Free Software Foundation; either version 3, or (at your option)
041dd5a9
ILT
10 any later version.
11
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.
16
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
4b4da160
NC
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
041dd5a9 21
a2429eb5 22/* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>. */
041dd5a9
ILT
23
24#include "as.h"
3882b010 25#include "safe-ctype.h"
041dd5a9
ILT
26#include "opcode/pj.h"
27
041dd5a9
ILT
28extern const pj_opc_info_t pj_opc_info[512];
29
ea1562b3 30const char comment_chars[] = "!/";
041dd5a9 31const char line_separator_chars[] = ";";
ea1562b3 32const char line_comment_chars[] = "/!#";
041dd5a9
ILT
33
34static int pending_reloc;
35static struct hash_control *opcode_hash_control;
041dd5a9
ILT
36
37static void
ea1562b3 38little (int ignore ATTRIBUTE_UNUSED)
041dd5a9
ILT
39{
40 target_big_endian = 0;
41}
42
43static void
ea1562b3 44big (int ignore ATTRIBUTE_UNUSED)
041dd5a9
ILT
45{
46 target_big_endian = 1;
47}
48
ea1562b3
NC
49const pseudo_typeS md_pseudo_table[] =
50{
041dd5a9
ILT
51 {"ml", little, 0},
52 {"mb", big, 0},
53 {0, 0, 0}
54};
55
041dd5a9
ILT
56const char FLT_CHARS[] = "rRsSfFdDxXpP";
57const char EXP_CHARS[] = "eE";
58
59void
ea1562b3 60md_operand (expressionS *op)
041dd5a9
ILT
61{
62 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
63 {
64 if (pending_reloc)
a2429eb5 65 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
66 pending_reloc = BFD_RELOC_PJ_CODE_HI16;
67 input_line_pointer += 5;
68 expression (op);
69 }
ea1562b3 70
041dd5a9
ILT
71 if (strncmp (input_line_pointer, "%lo16", 5) == 0)
72 {
73 if (pending_reloc)
a2429eb5 74 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
75 pending_reloc = BFD_RELOC_PJ_CODE_LO16;
76 input_line_pointer += 5;
77 expression (op);
78 }
79}
80
a2429eb5 81/* Parse an expression and then restore the input line pointer. */
041dd5a9
ILT
82
83static char *
ea1562b3 84parse_exp_save_ilp (char *s, expressionS *op)
041dd5a9
ILT
85{
86 char *save = input_line_pointer;
ea1562b3 87
041dd5a9
ILT
88 input_line_pointer = s;
89 expression (op);
90 s = input_line_pointer;
91 input_line_pointer = save;
92 return s;
93}
94
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. */
98
99void
ea1562b3 100pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp)
041dd5a9 101{
a2429eb5 102 static int rv[5][2] =
041dd5a9
ILT
103 { { 0, 0 },
104 { BFD_RELOC_8, BFD_RELOC_8 },
105 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
106 { 0, 0 },
107 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
108
a2429eb5 109 fix_new_exp (frag, where, nbytes, exp, 0,
041dd5a9 110 pending_reloc ? pending_reloc
a2429eb5 111 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
041dd5a9
ILT
112
113 pending_reloc = 0;
114}
115
041dd5a9 116/* Turn a reloc description character from the pj-opc.h table into
a2429eb5 117 code which BFD can handle. */
041dd5a9
ILT
118
119static int
ea1562b3 120c_to_r (int x)
041dd5a9
ILT
121{
122 switch (x)
123 {
124 case O_R8:
125 return BFD_RELOC_8_PCREL;
126 case O_U8:
127 case O_8:
128 return BFD_RELOC_8;
129 case O_R16:
130 return BFD_RELOC_PJ_CODE_REL16;
131 case O_U16:
132 case O_16:
133 return BFD_RELOC_PJ_CODE_DIR16;
134 case O_R32:
135 return BFD_RELOC_PJ_CODE_REL32;
136 case O_32:
137 return BFD_RELOC_PJ_CODE_DIR32;
138 }
139 abort ();
140 return 0;
141}
142
041dd5a9 143/* Handler for the ipush fake opcode,
a2429eb5 144 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
041dd5a9
ILT
145
146static void
ea1562b3 147ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str)
041dd5a9 148{
041dd5a9
ILT
149 char *b = frag_more (6);
150 expressionS arg;
a2429eb5 151
041dd5a9
ILT
152 b[0] = 0x11;
153 b[3] = 0xed;
0e073f4c
AM
154 parse_exp_save_ilp (str + 1, &arg);
155 if (pending_reloc)
156 {
157 as_bad (_("can't have relocation for ipush"));
158 pending_reloc = 0;
159 }
041dd5a9 160
a2429eb5
NC
161 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
162 &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
041dd5a9 163 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
a2429eb5 164 &arg, 0, BFD_RELOC_PJ_CODE_HI16);
041dd5a9
ILT
165}
166
167/* Insert names into the opcode table which are really mini macros,
67c1ffbe 168 not opcodes. The fakeness is indicated with an opcode of -1. */
041dd5a9
ILT
169
170static void
ea1562b3
NC
171fake_opcode (const char *name,
172 void (*func) (struct pj_opc_info_t *, char *))
041dd5a9 173{
ea1562b3 174 pj_opc_info_t * fake = xmalloc (sizeof (pj_opc_info_t));
041dd5a9
ILT
175
176 fake->opcode = -1;
177 fake->opcode_next = -1;
0e073f4c 178 fake->u.func = func;
041dd5a9
ILT
179 hash_insert (opcode_hash_control, name, (char *) fake);
180}
181
041dd5a9 182/* Enter another entry into the opcode hash table so the same opcode
a2429eb5
NC
183 can have another name. */
184
041dd5a9 185static void
d3ce72d0 186alias (const char *new_name, const char *old)
041dd5a9 187{
d3ce72d0 188 hash_insert (opcode_hash_control, new_name,
041dd5a9
ILT
189 (char *) hash_find (opcode_hash_control, old));
190}
191
041dd5a9
ILT
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
a2429eb5 194 some aliases for compatibility with other assemblers. */
041dd5a9
ILT
195
196void
ea1562b3 197md_begin (void)
041dd5a9
ILT
198{
199 const pj_opc_info_t *opcode;
200 opcode_hash_control = hash_new ();
201
a2429eb5 202 /* Insert names into hash table. */
0e073f4c
AM
203 for (opcode = pj_opc_info; opcode->u.name; opcode++)
204 hash_insert (opcode_hash_control, opcode->u.name, (char *) opcode);
041dd5a9 205
a2429eb5 206 /* Insert the only fake opcode. */
041dd5a9
ILT
207 fake_opcode ("ipush", ipush_code);
208
a2429eb5 209 /* Add some aliases for opcode names. */
041dd5a9
ILT
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");
217
218 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
219}
220
a2429eb5
NC
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. */
041dd5a9
ILT
224
225void
ea1562b3 226md_assemble (char *str)
041dd5a9 227{
2132e3a3
AM
228 char *op_start;
229 char *op_end;
041dd5a9 230
041dd5a9
ILT
231 pj_opc_info_t *opcode;
232 char *output;
233 int idx = 0;
234 char pend;
235
236 int nlen = 0;
237
a2429eb5 238 /* Drop leading whitespace. */
041dd5a9
ILT
239 while (*str == ' ')
240 str++;
241
a2429eb5 242 /* Find the op code end. */
2132e3a3
AM
243 op_start = str;
244 for (op_end = str;
245 *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
a2429eb5 246 op_end++)
041dd5a9
ILT
247 nlen++;
248
249 pend = *op_end;
250 *op_end = 0;
251
252 if (nlen == 0)
a2429eb5 253 as_bad (_("can't find opcode "));
041dd5a9
ILT
254
255 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
256 *op_end = pend;
257
258 if (opcode == NULL)
259 {
a2429eb5 260 as_bad (_("unknown opcode %s"), op_start);
041dd5a9
ILT
261 return;
262 }
263
264 if (opcode->opcode == -1)
265 {
a2429eb5
NC
266 /* It's a fake opcode. Dig out the args and pretend that was
267 what we were passed. */
0e073f4c 268 (*opcode->u.func) (opcode, op_end);
041dd5a9
ILT
269 }
270 else
271 {
272 int an;
273
274 output = frag_more (opcode->len);
275 output[idx++] = opcode->opcode;
276
277 if (opcode->opcode_next != -1)
278 output[idx++] = opcode->opcode_next;
279
280 for (an = 0; opcode->arg[an]; an++)
281 {
282 expressionS arg;
283
284 if (*op_end == ',' && an != 0)
285 op_end++;
286
287 if (*op_end == 0)
20203fb9 288 as_bad (_("expected expresssion"));
041dd5a9
ILT
289
290 op_end = parse_exp_save_ilp (op_end, &arg);
291
a2429eb5 292 fix_new_exp (frag_now,
041dd5a9
ILT
293 output - frag_now->fr_literal + idx,
294 ASIZE (opcode->arg[an]),
295 &arg,
a2429eb5 296 PCREL (opcode->arg[an]),
041dd5a9
ILT
297 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
298
299 idx += ASIZE (opcode->arg[an]);
300 pending_reloc = 0;
301 }
302
3882b010 303 while (ISSPACE (*op_end))
041dd5a9
ILT
304 op_end++;
305
306 if (*op_end != 0)
20203fb9 307 as_warn (_("extra stuff on line ignored"));
041dd5a9
ILT
308
309 }
310
311 if (pending_reloc)
20203fb9 312 as_bad (_("Something forgot to clean up\n"));
041dd5a9
ILT
313}
314
041dd5a9 315char *
ea1562b3 316md_atof (int type, char *litP, int *sizeP)
041dd5a9 317{
499ac353 318 return ieee_md_atof (type, litP, sizeP, target_big_endian);
041dd5a9
ILT
319}
320\f
5a38dc70 321const char *md_shortopts = "";
041dd5a9 322
ea1562b3
NC
323struct option md_longopts[] =
324{
041dd5a9
ILT
325#define OPTION_LITTLE (OPTION_MD_BASE)
326#define OPTION_BIG (OPTION_LITTLE + 1)
327
328 {"little", no_argument, NULL, OPTION_LITTLE},
329 {"big", no_argument, NULL, OPTION_BIG},
330 {NULL, no_argument, NULL, 0}
331};
332size_t md_longopts_size = sizeof (md_longopts);
333
334int
ea1562b3 335md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
041dd5a9
ILT
336{
337 switch (c)
338 {
339 case OPTION_LITTLE:
0e073f4c 340 little (0);
041dd5a9
ILT
341 break;
342 case OPTION_BIG:
0e073f4c 343 big (0);
041dd5a9
ILT
344 break;
345 default:
346 return 0;
347 }
348 return 1;
349}
350
351void
ea1562b3 352md_show_usage (FILE *stream)
041dd5a9 353{
a2429eb5 354 fprintf (stream, _("\
041dd5a9
ILT
355PJ options:\n\
356-little generate little endian code\n\
357-big generate big endian code\n"));
358}
359
041dd5a9
ILT
360/* Apply a fixup to the object file. */
361
94f592af 362void
55cf6793 363md_apply_fix (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
041dd5a9
ILT
364{
365 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
a161fe53 366 long val = *valP;
041dd5a9
ILT
367 long max, min;
368 int shift;
369
041dd5a9
ILT
370 max = min = 0;
371 shift = 0;
372 switch (fixP->fx_r_type)
373 {
374 case BFD_RELOC_VTABLE_INHERIT:
375 case BFD_RELOC_VTABLE_ENTRY:
376 fixP->fx_done = 0;
94f592af 377 return;
041dd5a9
ILT
378
379 case BFD_RELOC_PJ_CODE_REL16:
380 if (val < -0x8000 || val >= 0x7fff)
a2429eb5 381 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
041dd5a9
ILT
382 buf[0] |= (val >> 8) & 0xff;
383 buf[1] = val & 0xff;
384 break;
385
386 case BFD_RELOC_PJ_CODE_HI16:
387 *buf++ = val >> 24;
388 *buf++ = val >> 16;
389 fixP->fx_addnumber = val & 0xffff;
390 break;
391
392 case BFD_RELOC_PJ_CODE_DIR16:
393 case BFD_RELOC_PJ_CODE_LO16:
394 *buf++ = val >> 8;
395 *buf++ = val >> 0;
396
397 max = 0xffff;
398 min = -0xffff;
399 break;
400
401 case BFD_RELOC_8:
402 max = 0xff;
403 min = -0xff;
404 *buf++ = val;
405 break;
406
407 case BFD_RELOC_PJ_CODE_DIR32:
408 *buf++ = val >> 24;
409 *buf++ = val >> 16;
410 *buf++ = val >> 8;
411 *buf++ = val >> 0;
412 break;
413
414 case BFD_RELOC_32:
415 if (target_big_endian)
416 {
417 *buf++ = val >> 24;
418 *buf++ = val >> 16;
419 *buf++ = val >> 8;
420 *buf++ = val >> 0;
421 }
a2429eb5 422 else
041dd5a9
ILT
423 {
424 *buf++ = val >> 0;
425 *buf++ = val >> 8;
426 *buf++ = val >> 16;
427 *buf++ = val >> 24;
428 }
429 break;
430
431 case BFD_RELOC_16:
432 if (target_big_endian)
433 {
434 *buf++ = val >> 8;
435 *buf++ = val >> 0;
436 }
437 else
438 {
439 *buf++ = val >> 0;
440 *buf++ = val >> 8;
441 }
442 break;
443
041dd5a9
ILT
444 default:
445 abort ();
446 }
447
448 if (max != 0 && (val < min || val > max))
a2429eb5 449 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
041dd5a9 450
94f592af
NC
451 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
452 fixP->fx_done = 1;
041dd5a9
ILT
453}
454
455/* Put number into target byte order. Always put values in an
a2429eb5 456 executable section into big endian order. */
041dd5a9
ILT
457
458void
ea1562b3 459md_number_to_chars (char *ptr, valueT use, int nbytes)
041dd5a9
ILT
460{
461 if (target_big_endian || now_seg->flags & SEC_CODE)
462 number_to_chars_bigendian (ptr, use, nbytes);
463 else
464 number_to_chars_littleendian (ptr, use, nbytes);
465}
466
041dd5a9 467/* Translate internal representation of relocation info to BFD target
a2429eb5 468 format. */
041dd5a9
ILT
469
470arelent *
ea1562b3 471tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
041dd5a9
ILT
472{
473 arelent *rel;
474 bfd_reloc_code_real_type r_type;
475
ea1562b3
NC
476 rel = xmalloc (sizeof (arelent));
477 rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
041dd5a9
ILT
478 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
479 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
480
481 r_type = fixp->fx_r_type;
482 rel->addend = fixp->fx_addnumber;
483 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
484
485 if (rel->howto == NULL)
486 {
487 as_bad_where (fixp->fx_file, fixp->fx_line,
a2429eb5 488 _("Cannot represent relocation type %s"),
041dd5a9
ILT
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);
9c2799c2 492 gas_assert (rel->howto != NULL);
041dd5a9
ILT
493 }
494
495 return rel;
496}
This page took 0.455974 seconds and 4 git commands to generate.