* remote.c (struct packet_reg): Declare.
[deliverable/binutils-gdb.git] / gas / config / tc-pj.c
CommitLineData
041dd5a9
ILT
1/*-
2 tc-pj.c -- Assemble code for Pico Java
3882b010 3 Copyright 1999, 2000, 2001 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
9 the Free Software Foundation; either version 2, or (at your option)
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
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
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
30const char comment_chars[] = "!/";
31const char line_separator_chars[] = ";";
32const char line_comment_chars[] = "/!#";
33
34static int pending_reloc;
35static struct hash_control *opcode_hash_control;
041dd5a9
ILT
36
37static void
38little (ignore)
39 int ignore ATTRIBUTE_UNUSED;
40{
41 target_big_endian = 0;
42}
43
44static void
45big (ignore)
46 int ignore ATTRIBUTE_UNUSED;
47{
48 target_big_endian = 1;
49}
50
041dd5a9
ILT
51const pseudo_typeS md_pseudo_table[] = {
52 {"ml", little, 0},
53 {"mb", big, 0},
54 {0, 0, 0}
55};
56
041dd5a9
ILT
57const char FLT_CHARS[] = "rRsSfFdDxXpP";
58const char EXP_CHARS[] = "eE";
59
60void
61md_operand (op)
62 expressionS *op;
63{
64 if (strncmp (input_line_pointer, "%hi16", 5) == 0)
65 {
66 if (pending_reloc)
a2429eb5 67 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
68 pending_reloc = BFD_RELOC_PJ_CODE_HI16;
69 input_line_pointer += 5;
70 expression (op);
71 }
72 if (strncmp (input_line_pointer, "%lo16", 5) == 0)
73 {
74 if (pending_reloc)
a2429eb5 75 as_bad (_("confusing relocation expressions"));
041dd5a9
ILT
76 pending_reloc = BFD_RELOC_PJ_CODE_LO16;
77 input_line_pointer += 5;
78 expression (op);
79 }
80}
81
a2429eb5 82/* Parse an expression and then restore the input line pointer. */
041dd5a9
ILT
83
84static char *
85parse_exp_save_ilp (s, op)
86 char *s;
87 expressionS *op;
88{
89 char *save = input_line_pointer;
90 input_line_pointer = s;
91 expression (op);
92 s = input_line_pointer;
93 input_line_pointer = save;
94 return s;
95}
96
97/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
98 reloc for a cons. We could use the definition there, except that
99 we want to handle magic pending reloc expressions specially. */
100
101void
102pj_cons_fix_new_pj (frag, where, nbytes, exp)
103 fragS *frag;
104 int where;
105 int nbytes;
106 expressionS *exp;
107{
a2429eb5 108 static int rv[5][2] =
041dd5a9
ILT
109 { { 0, 0 },
110 { BFD_RELOC_8, BFD_RELOC_8 },
111 { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
112 { 0, 0 },
113 { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
114
a2429eb5 115 fix_new_exp (frag, where, nbytes, exp, 0,
041dd5a9 116 pending_reloc ? pending_reloc
a2429eb5 117 : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
041dd5a9
ILT
118
119 pending_reloc = 0;
120}
121
041dd5a9 122/* Turn a reloc description character from the pj-opc.h table into
a2429eb5 123 code which BFD can handle. */
041dd5a9
ILT
124
125static int
126c_to_r (x)
127 char x;
128{
129 switch (x)
130 {
131 case O_R8:
132 return BFD_RELOC_8_PCREL;
133 case O_U8:
134 case O_8:
135 return BFD_RELOC_8;
136 case O_R16:
137 return BFD_RELOC_PJ_CODE_REL16;
138 case O_U16:
139 case O_16:
140 return BFD_RELOC_PJ_CODE_DIR16;
141 case O_R32:
142 return BFD_RELOC_PJ_CODE_REL32;
143 case O_32:
144 return BFD_RELOC_PJ_CODE_DIR32;
145 }
146 abort ();
147 return 0;
148}
149
041dd5a9 150/* Handler for the ipush fake opcode,
a2429eb5 151 turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>. */
041dd5a9
ILT
152
153static void
154ipush_code (opcode, str)
a2429eb5 155 pj_opc_info_t *opcode ATTRIBUTE_UNUSED;
041dd5a9
ILT
156 char *str;
157{
158 int mod = 0;
159 char *b = frag_more (6);
160 expressionS arg;
a2429eb5 161
041dd5a9
ILT
162 b[0] = 0x11;
163 b[3] = 0xed;
164 parse_exp_save_ilp (str + 1, &arg, &mod);
165 if (mod)
a2429eb5 166 as_bad (_("can't have relocation for ipush"));
041dd5a9 167
a2429eb5
NC
168 fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
169 &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
041dd5a9 170 fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
a2429eb5 171 &arg, 0, BFD_RELOC_PJ_CODE_HI16);
041dd5a9
ILT
172}
173
174/* Insert names into the opcode table which are really mini macros,
a2429eb5 175 not opcodes. The fakeness is inidicated with an opcode of -1. */
041dd5a9
ILT
176
177static void
a2429eb5
NC
178fake_opcode (name, func)
179 const char *name;
041dd5a9
ILT
180 void (*func) ();
181{
182 pj_opc_info_t *fake = (pj_opc_info_t *) xmalloc (sizeof (pj_opc_info_t));
183
184 fake->opcode = -1;
185 fake->opcode_next = -1;
186 fake->name = (const char *) func;
187 hash_insert (opcode_hash_control, name, (char *) fake);
188}
189
041dd5a9 190/* Enter another entry into the opcode hash table so the same opcode
a2429eb5
NC
191 can have another name. */
192
041dd5a9 193static void
a2429eb5
NC
194alias (new, old)
195 const char *new;
041dd5a9
ILT
196 const char *old;
197{
198 hash_insert (opcode_hash_control, new,
199 (char *) hash_find (opcode_hash_control, old));
200}
201
041dd5a9
ILT
202/* This function is called once, at assembler startup time. It sets
203 up the hash table with all the opcodes in it, and also initializes
a2429eb5 204 some aliases for compatibility with other assemblers. */
041dd5a9
ILT
205
206void
207md_begin ()
208{
209 const pj_opc_info_t *opcode;
210 opcode_hash_control = hash_new ();
211
a2429eb5 212 /* Insert names into hash table. */
041dd5a9
ILT
213 for (opcode = pj_opc_info; opcode->name; opcode++)
214 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
215
a2429eb5 216 /* Insert the only fake opcode. */
041dd5a9
ILT
217 fake_opcode ("ipush", ipush_code);
218
a2429eb5 219 /* Add some aliases for opcode names. */
041dd5a9
ILT
220 alias ("ifeq_s", "ifeq");
221 alias ("ifne_s", "ifne");
222 alias ("if_icmpge_s", "if_icmpge");
223 alias ("if_icmpne_s", "if_icmpne");
224 alias ("if_icmpeq_s", "if_icmpeq");
225 alias ("if_icmpgt_s", "if_icmpgt");
226 alias ("goto_s", "goto");
227
228 bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
229}
230
a2429eb5
NC
231/* This is the guts of the machine-dependent assembler. STR points to
232 a machine dependent instruction. This function is supposed to emit
233 the frags/bytes it assembles to. */
041dd5a9
ILT
234
235void
236md_assemble (str)
237 char *str;
238{
239 unsigned char *op_start;
240 unsigned char *op_end;
241
a2429eb5
NC
242#if 0
243 pj_operan_info operand[3];
244#endif
041dd5a9
ILT
245 pj_opc_info_t *opcode;
246 char *output;
247 int idx = 0;
248 char pend;
249
250 int nlen = 0;
251
a2429eb5 252 /* Drop leading whitespace. */
041dd5a9
ILT
253 while (*str == ' ')
254 str++;
255
a2429eb5 256 /* Find the op code end. */
041dd5a9
ILT
257 for (op_start = op_end = (unsigned char *) (str);
258 *op_end && !is_end_of_line[*op_end] && *op_end != ' ';
a2429eb5 259 op_end++)
041dd5a9
ILT
260 nlen++;
261
262 pend = *op_end;
263 *op_end = 0;
264
265 if (nlen == 0)
a2429eb5 266 as_bad (_("can't find opcode "));
041dd5a9
ILT
267
268 opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
269 *op_end = pend;
270
271 if (opcode == NULL)
272 {
a2429eb5 273 as_bad (_("unknown opcode %s"), op_start);
041dd5a9
ILT
274 return;
275 }
276
277 if (opcode->opcode == -1)
278 {
a2429eb5
NC
279 /* It's a fake opcode. Dig out the args and pretend that was
280 what we were passed. */
bc805888 281 ((void (*) ()) opcode->name) (opcode, op_end);
041dd5a9
ILT
282 }
283 else
284 {
285 int an;
286
287 output = frag_more (opcode->len);
288 output[idx++] = opcode->opcode;
289
290 if (opcode->opcode_next != -1)
291 output[idx++] = opcode->opcode_next;
292
293 for (an = 0; opcode->arg[an]; an++)
294 {
295 expressionS arg;
296
297 if (*op_end == ',' && an != 0)
298 op_end++;
299
300 if (*op_end == 0)
301 as_bad ("expected expresssion");
302
303 op_end = parse_exp_save_ilp (op_end, &arg);
304
a2429eb5 305 fix_new_exp (frag_now,
041dd5a9
ILT
306 output - frag_now->fr_literal + idx,
307 ASIZE (opcode->arg[an]),
308 &arg,
a2429eb5 309 PCREL (opcode->arg[an]),
041dd5a9
ILT
310 pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
311
312 idx += ASIZE (opcode->arg[an]);
313 pending_reloc = 0;
314 }
315
3882b010 316 while (ISSPACE (*op_end))
041dd5a9
ILT
317 op_end++;
318
319 if (*op_end != 0)
320 as_warn ("extra stuff on line ignored");
321
322 }
323
324 if (pending_reloc)
325 as_bad ("Something forgot to clean up\n");
326
327}
328
a2429eb5
NC
329/* Turn a string in input_line_pointer into a floating point constant
330 of type type, and store the appropriate bytes in *LITP. The number
331 of LITTLENUMS emitted is stored in *SIZEP . An error message is
332 returned, or NULL on OK. */
333
041dd5a9
ILT
334char *
335md_atof (type, litP, sizeP)
336 int type;
337 char *litP;
338 int *sizeP;
339{
340 int prec;
341 LITTLENUM_TYPE words[4];
342 char *t;
343 int i;
344
345 switch (type)
346 {
347 case 'f':
348 prec = 2;
349 break;
350
351 case 'd':
352 prec = 4;
353 break;
354
355 default:
356 *sizeP = 0;
a2429eb5 357 return _("bad call to md_atof");
041dd5a9
ILT
358 }
359
360 t = atof_ieee (input_line_pointer, type, words);
361 if (t)
362 input_line_pointer = t;
363
364 *sizeP = prec * 2;
365
366 if (!target_big_endian)
367 {
368 for (i = prec - 1; i >= 0; i--)
369 {
370 md_number_to_chars (litP, (valueT) words[i], 2);
371 litP += 2;
372 }
373 }
374 else
375 {
376 for (i = 0; i < prec; i++)
377 {
378 md_number_to_chars (litP, (valueT) words[i], 2);
379 litP += 2;
380 }
381 }
382
383 return NULL;
384}
385\f
041dd5a9
ILT
386CONST char *md_shortopts = "";
387
388struct option md_longopts[] = {
389
390#define OPTION_LITTLE (OPTION_MD_BASE)
391#define OPTION_BIG (OPTION_LITTLE + 1)
392
393 {"little", no_argument, NULL, OPTION_LITTLE},
394 {"big", no_argument, NULL, OPTION_BIG},
395 {NULL, no_argument, NULL, 0}
396};
397size_t md_longopts_size = sizeof (md_longopts);
398
399int
400md_parse_option (c, arg)
401 int c;
a2429eb5 402 char *arg ATTRIBUTE_UNUSED;
041dd5a9
ILT
403{
404 switch (c)
405 {
406 case OPTION_LITTLE:
407 little ();
408 break;
409 case OPTION_BIG:
410 big ();
411 break;
412 default:
413 return 0;
414 }
415 return 1;
416}
417
418void
419md_show_usage (stream)
420 FILE *stream;
421{
a2429eb5 422 fprintf (stream, _("\
041dd5a9
ILT
423PJ options:\n\
424-little generate little endian code\n\
425-big generate big endian code\n"));
426}
427
041dd5a9
ILT
428/* Apply a fixup to the object file. */
429
041dd5a9
ILT
430int
431md_apply_fix (fixP, valp)
432 fixS *fixP;
433 valueT *valp;
434{
435 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
436 long val = *valp;
437 long max, min;
438 int shift;
439
041dd5a9
ILT
440 /* adjust_reloc_syms won't convert a reloc against a weak symbol
441 into a reloc against a section, but bfd_install_relocation will
442 screw up if the symbol is defined, so we have to adjust val here
443 to avoid the screw up later. */
444
445 if (fixP->fx_addsy != NULL && S_IS_WEAK (fixP->fx_addsy))
446 val -= S_GET_VALUE (fixP->fx_addsy);
447
448 max = min = 0;
449 shift = 0;
450 switch (fixP->fx_r_type)
451 {
452 case BFD_RELOC_VTABLE_INHERIT:
453 case BFD_RELOC_VTABLE_ENTRY:
454 fixP->fx_done = 0;
455 return 0;
456
457 case BFD_RELOC_PJ_CODE_REL16:
458 if (val < -0x8000 || val >= 0x7fff)
a2429eb5 459 as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
041dd5a9
ILT
460 buf[0] |= (val >> 8) & 0xff;
461 buf[1] = val & 0xff;
462 break;
463
464 case BFD_RELOC_PJ_CODE_HI16:
465 *buf++ = val >> 24;
466 *buf++ = val >> 16;
467 fixP->fx_addnumber = val & 0xffff;
468 break;
469
470 case BFD_RELOC_PJ_CODE_DIR16:
471 case BFD_RELOC_PJ_CODE_LO16:
472 *buf++ = val >> 8;
473 *buf++ = val >> 0;
474
475 max = 0xffff;
476 min = -0xffff;
477 break;
478
479 case BFD_RELOC_8:
480 max = 0xff;
481 min = -0xff;
482 *buf++ = val;
483 break;
484
485 case BFD_RELOC_PJ_CODE_DIR32:
486 *buf++ = val >> 24;
487 *buf++ = val >> 16;
488 *buf++ = val >> 8;
489 *buf++ = val >> 0;
490 break;
491
492 case BFD_RELOC_32:
493 if (target_big_endian)
494 {
495 *buf++ = val >> 24;
496 *buf++ = val >> 16;
497 *buf++ = val >> 8;
498 *buf++ = val >> 0;
499 }
a2429eb5 500 else
041dd5a9
ILT
501 {
502 *buf++ = val >> 0;
503 *buf++ = val >> 8;
504 *buf++ = val >> 16;
505 *buf++ = val >> 24;
506 }
507 break;
508
509 case BFD_RELOC_16:
510 if (target_big_endian)
511 {
512 *buf++ = val >> 8;
513 *buf++ = val >> 0;
514 }
515 else
516 {
517 *buf++ = val >> 0;
518 *buf++ = val >> 8;
519 }
520 break;
521
041dd5a9
ILT
522 default:
523 abort ();
524 }
525
526 if (max != 0 && (val < min || val > max))
a2429eb5 527 as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
041dd5a9
ILT
528
529 return 0;
530}
531
532/* Put number into target byte order. Always put values in an
a2429eb5 533 executable section into big endian order. */
041dd5a9
ILT
534
535void
536md_number_to_chars (ptr, use, nbytes)
537 char *ptr;
538 valueT use;
539 int nbytes;
540{
541 if (target_big_endian || now_seg->flags & SEC_CODE)
542 number_to_chars_bigendian (ptr, use, nbytes);
543 else
544 number_to_chars_littleendian (ptr, use, nbytes);
545}
546
041dd5a9 547/* Translate internal representation of relocation info to BFD target
a2429eb5 548 format. */
041dd5a9
ILT
549
550arelent *
551tc_gen_reloc (section, fixp)
552 asection *section ATTRIBUTE_UNUSED;
553 fixS *fixp;
554{
555 arelent *rel;
556 bfd_reloc_code_real_type r_type;
557
558 rel = (arelent *) xmalloc (sizeof (arelent));
559 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
560 *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
561 rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
562
563 r_type = fixp->fx_r_type;
564 rel->addend = fixp->fx_addnumber;
565 rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
566
567 if (rel->howto == NULL)
568 {
569 as_bad_where (fixp->fx_file, fixp->fx_line,
a2429eb5 570 _("Cannot represent relocation type %s"),
041dd5a9
ILT
571 bfd_get_reloc_code_name (r_type));
572 /* Set howto to a garbage value so that we can keep going. */
573 rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
574 assert (rel->howto != NULL);
575 }
576
577 return rel;
578}
This page took 0.108004 seconds and 4 git commands to generate.