daily update
[binutils/dougsmingw.git] / gas / config / tc-mn10200.c
blobf9bf78b84529a605ccaeafaf94be3fe7aa6799f5
1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
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 3, or (at your option)
10 any later version.
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, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include "as.h"
23 #include "safe-ctype.h"
24 #include "subsegs.h"
25 #include "opcode/mn10200.h"
27 /* Structure to hold information about predefined registers. */
28 struct reg_name
30 const char *name;
31 int value;
34 /* Generic assembler global variables which must be defined by all
35 targets. */
37 /* Characters which always start a comment. */
38 const char comment_chars[] = "#";
40 /* Characters which start a comment at the beginning of a line. */
41 const char line_comment_chars[] = ";#";
43 /* Characters which may be used to separate multiple commands on a
44 single line. */
45 const char line_separator_chars[] = ";";
47 /* Characters which are used to indicate an exponent in a floating
48 point number. */
49 const char EXP_CHARS[] = "eE";
51 /* Characters which mean that a number is a floating point constant,
52 as in 0d1.0. */
53 const char FLT_CHARS[] = "dD";
55 const relax_typeS md_relax_table[] =
57 /* bCC relaxing */
58 {0x81, -0x7e, 2, 1},
59 {0x8004, -0x7ffb, 5, 2},
60 {0x800006, -0x7ffff9, 7, 0},
61 /* bCCx relaxing */
62 {0x81, -0x7e, 3, 4},
63 {0x8004, -0x7ffb, 6, 5},
64 {0x800006, -0x7ffff9, 8, 0},
65 /* jsr relaxing */
66 {0x8004, -0x7ffb, 3, 7},
67 {0x800006, -0x7ffff9, 5, 0},
68 /* jmp relaxing */
69 {0x81, -0x7e, 2, 9},
70 {0x8004, -0x7ffb, 3, 10},
71 {0x800006, -0x7ffff9, 5, 0},
76 /* Fixups. */
77 #define MAX_INSN_FIXUPS 5
79 struct mn10200_fixup
81 expressionS exp;
82 int opindex;
83 bfd_reloc_code_real_type reloc;
86 struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
87 static int fc;
89 const char *md_shortopts = "";
91 struct option md_longopts[] =
93 {NULL, no_argument, NULL, 0}
96 size_t md_longopts_size = sizeof (md_longopts);
98 /* The target specific pseudo-ops which we support. */
99 const pseudo_typeS md_pseudo_table[] =
101 { NULL, NULL, 0 }
104 /* Opcode hash table. */
105 static struct hash_control *mn10200_hash;
107 /* This table is sorted. Suitable for searching by a binary search. */
108 static const struct reg_name data_registers[] =
110 { "d0", 0 },
111 { "d1", 1 },
112 { "d2", 2 },
113 { "d3", 3 },
115 #define DATA_REG_NAME_CNT \
116 (sizeof (data_registers) / sizeof (struct reg_name))
118 static const struct reg_name address_registers[] =
120 { "a0", 0 },
121 { "a1", 1 },
122 { "a2", 2 },
123 { "a3", 3 },
125 #define ADDRESS_REG_NAME_CNT \
126 (sizeof (address_registers) / sizeof (struct reg_name))
128 static const struct reg_name other_registers[] =
130 { "mdr", 0 },
131 { "psw", 0 },
133 #define OTHER_REG_NAME_CNT \
134 (sizeof (other_registers) / sizeof (struct reg_name))
136 /* reg_name_search does a binary search of the given register table
137 to see if "name" is a valid regiter name. Returns the register
138 number from the array on success, or -1 on failure. */
140 static int
141 reg_name_search (const struct reg_name *regs,
142 int regcount,
143 const char *name)
145 int middle, low, high;
146 int cmp;
148 low = 0;
149 high = regcount - 1;
153 middle = (low + high) / 2;
154 cmp = strcasecmp (name, regs[middle].name);
155 if (cmp < 0)
156 high = middle - 1;
157 else if (cmp > 0)
158 low = middle + 1;
159 else
160 return regs[middle].value;
162 while (low <= high);
163 return -1;
166 /* Summary of register_name().
168 in: Input_line_pointer points to 1st char of operand.
170 out: An expressionS.
171 The operand may have been a register: in this case, X_op == O_register,
172 X_add_number is set to the register number, and truth is returned.
173 Input_line_pointer->(next non-blank) char after operand, or is in
174 its original state. */
176 static bfd_boolean
177 data_register_name (expressionS *expressionP)
179 int reg_number;
180 char *name;
181 char *start;
182 char c;
184 /* Find the spelling of the operand. */
185 start = name = input_line_pointer;
187 c = get_symbol_end ();
188 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
190 /* Put back the delimiting char. */
191 *input_line_pointer = c;
193 /* Look to see if it's in the register table. */
194 if (reg_number >= 0)
196 expressionP->X_op = O_register;
197 expressionP->X_add_number = reg_number;
199 /* Make the rest nice. */
200 expressionP->X_add_symbol = NULL;
201 expressionP->X_op_symbol = NULL;
203 return TRUE;
206 /* Reset the line as if we had not done anything. */
207 input_line_pointer = start;
208 return FALSE;
211 /* Summary of register_name().
213 in: Input_line_pointer points to 1st char of operand.
215 out: An expressionS.
216 The operand may have been a register: in this case, X_op == O_register,
217 X_add_number is set to the register number, and truth is returned.
218 Input_line_pointer->(next non-blank) char after operand, or is in
219 its original state. */
221 static bfd_boolean
222 address_register_name (expressionS *expressionP)
224 int reg_number;
225 char *name;
226 char *start;
227 char c;
229 /* Find the spelling of the operand. */
230 start = name = input_line_pointer;
232 c = get_symbol_end ();
233 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
235 /* Put back the delimiting char. */
236 *input_line_pointer = c;
238 /* Look to see if it's in the register table. */
239 if (reg_number >= 0)
241 expressionP->X_op = O_register;
242 expressionP->X_add_number = reg_number;
244 /* Make the rest nice. */
245 expressionP->X_add_symbol = NULL;
246 expressionP->X_op_symbol = NULL;
248 return TRUE;
251 /* Reset the line as if we had not done anything. */
252 input_line_pointer = start;
253 return FALSE;
256 /* Summary of register_name().
258 in: Input_line_pointer points to 1st char of operand.
260 out: An expressionS.
261 The operand may have been a register: in this case, X_op == O_register,
262 X_add_number is set to the register number, and truth is returned.
263 Input_line_pointer->(next non-blank) char after operand, or is in
264 its original state. */
266 static bfd_boolean
267 other_register_name (expressionS *expressionP)
269 int reg_number;
270 char *name;
271 char *start;
272 char c;
274 /* Find the spelling of the operand. */
275 start = name = input_line_pointer;
277 c = get_symbol_end ();
278 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
280 /* Put back the delimiting char. */
281 *input_line_pointer = c;
283 /* Look to see if it's in the register table. */
284 if (reg_number >= 0)
286 expressionP->X_op = O_register;
287 expressionP->X_add_number = reg_number;
289 /* Make the rest nice. */
290 expressionP->X_add_symbol = NULL;
291 expressionP->X_op_symbol = NULL;
293 return TRUE;
296 /* Reset the line as if we had not done anything. */
297 input_line_pointer = start;
298 return FALSE;
301 void
302 md_show_usage (FILE *stream)
304 fprintf (stream, _("MN10200 options:\n\
305 none yet\n"));
309 md_parse_option (int c ATTRIBUTE_UNUSED,
310 char *arg ATTRIBUTE_UNUSED)
312 return 0;
315 symbolS *
316 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
318 return 0;
321 char *
322 md_atof (int type, char *litp, int *sizep)
324 return ieee_md_atof (type, litp, sizep, FALSE);
327 void
328 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
329 asection *sec,
330 fragS *fragP)
332 static unsigned long label_count = 0;
333 char buf[40];
335 subseg_change (sec, 0);
336 if (fragP->fr_subtype == 0)
338 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
339 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
340 fragP->fr_var = 0;
341 fragP->fr_fix += 2;
343 else if (fragP->fr_subtype == 1)
345 /* Reverse the condition of the first branch. */
346 int offset = fragP->fr_fix;
347 int opcode = fragP->fr_literal[offset] & 0xff;
349 switch (opcode)
351 case 0xe8:
352 opcode = 0xe9;
353 break;
354 case 0xe9:
355 opcode = 0xe8;
356 break;
357 case 0xe0:
358 opcode = 0xe2;
359 break;
360 case 0xe2:
361 opcode = 0xe0;
362 break;
363 case 0xe3:
364 opcode = 0xe1;
365 break;
366 case 0xe1:
367 opcode = 0xe3;
368 break;
369 case 0xe4:
370 opcode = 0xe6;
371 break;
372 case 0xe6:
373 opcode = 0xe4;
374 break;
375 case 0xe7:
376 opcode = 0xe5;
377 break;
378 case 0xe5:
379 opcode = 0xe7;
380 break;
381 default:
382 abort ();
384 fragP->fr_literal[offset] = opcode;
386 /* Create a fixup for the reversed conditional branch. */
387 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
388 fix_new (fragP, fragP->fr_fix + 1, 1,
389 symbol_new (buf, sec, 0, fragP->fr_next),
390 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
392 /* Now create the unconditional branch + fixup to the
393 final target. */
394 fragP->fr_literal[offset + 2] = 0xfc;
395 fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
396 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
397 fragP->fr_var = 0;
398 fragP->fr_fix += 5;
400 else if (fragP->fr_subtype == 2)
402 /* Reverse the condition of the first branch. */
403 int offset = fragP->fr_fix;
404 int opcode = fragP->fr_literal[offset] & 0xff;
406 switch (opcode)
408 case 0xe8:
409 opcode = 0xe9;
410 break;
411 case 0xe9:
412 opcode = 0xe8;
413 break;
414 case 0xe0:
415 opcode = 0xe2;
416 break;
417 case 0xe2:
418 opcode = 0xe0;
419 break;
420 case 0xe3:
421 opcode = 0xe1;
422 break;
423 case 0xe1:
424 opcode = 0xe3;
425 break;
426 case 0xe4:
427 opcode = 0xe6;
428 break;
429 case 0xe6:
430 opcode = 0xe4;
431 break;
432 case 0xe7:
433 opcode = 0xe5;
434 break;
435 case 0xe5:
436 opcode = 0xe7;
437 break;
438 default:
439 abort ();
441 fragP->fr_literal[offset] = opcode;
443 /* Create a fixup for the reversed conditional branch. */
444 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
445 fix_new (fragP, fragP->fr_fix + 1, 1,
446 symbol_new (buf, sec, 0, fragP->fr_next),
447 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
449 /* Now create the unconditional branch + fixup to the
450 final target. */
451 fragP->fr_literal[offset + 2] = 0xf4;
452 fragP->fr_literal[offset + 3] = 0xe0;
453 fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
454 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
455 fragP->fr_var = 0;
456 fragP->fr_fix += 7;
458 else if (fragP->fr_subtype == 3)
460 fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
461 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
462 fragP->fr_var = 0;
463 fragP->fr_fix += 3;
465 else if (fragP->fr_subtype == 4)
467 /* Reverse the condition of the first branch. */
468 int offset = fragP->fr_fix;
469 int opcode = fragP->fr_literal[offset + 1] & 0xff;
471 switch (opcode)
473 case 0xfc:
474 opcode = 0xfd;
475 break;
476 case 0xfd:
477 opcode = 0xfc;
478 break;
479 case 0xfe:
480 opcode = 0xff;
481 break;
482 case 0xff:
483 opcode = 0xfe;
484 case 0xe8:
485 opcode = 0xe9;
486 break;
487 case 0xe9:
488 opcode = 0xe8;
489 break;
490 case 0xe0:
491 opcode = 0xe2;
492 break;
493 case 0xe2:
494 opcode = 0xe0;
495 break;
496 case 0xe3:
497 opcode = 0xe1;
498 break;
499 case 0xe1:
500 opcode = 0xe3;
501 break;
502 case 0xe4:
503 opcode = 0xe6;
504 break;
505 case 0xe6:
506 opcode = 0xe4;
507 break;
508 case 0xe7:
509 opcode = 0xe5;
510 break;
511 case 0xe5:
512 opcode = 0xe7;
513 break;
514 case 0xec:
515 opcode = 0xed;
516 break;
517 case 0xed:
518 opcode = 0xec;
519 break;
520 case 0xee:
521 opcode = 0xef;
522 break;
523 case 0xef:
524 opcode = 0xee;
525 break;
526 default:
527 abort ();
529 fragP->fr_literal[offset + 1] = opcode;
531 /* Create a fixup for the reversed conditional branch. */
532 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
533 fix_new (fragP, fragP->fr_fix + 2, 1,
534 symbol_new (buf, sec, 0, fragP->fr_next),
535 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
537 /* Now create the unconditional branch + fixup to the
538 final target. */
539 fragP->fr_literal[offset + 3] = 0xfc;
540 fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
541 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
542 fragP->fr_var = 0;
543 fragP->fr_fix += 6;
545 else if (fragP->fr_subtype == 5)
547 /* Reverse the condition of the first branch. */
548 int offset = fragP->fr_fix;
549 int opcode = fragP->fr_literal[offset + 1] & 0xff;
551 switch (opcode)
553 case 0xfc:
554 opcode = 0xfd;
555 break;
556 case 0xfd:
557 opcode = 0xfc;
558 break;
559 case 0xfe:
560 opcode = 0xff;
561 break;
562 case 0xff:
563 opcode = 0xfe;
564 case 0xe8:
565 opcode = 0xe9;
566 break;
567 case 0xe9:
568 opcode = 0xe8;
569 break;
570 case 0xe0:
571 opcode = 0xe2;
572 break;
573 case 0xe2:
574 opcode = 0xe0;
575 break;
576 case 0xe3:
577 opcode = 0xe1;
578 break;
579 case 0xe1:
580 opcode = 0xe3;
581 break;
582 case 0xe4:
583 opcode = 0xe6;
584 break;
585 case 0xe6:
586 opcode = 0xe4;
587 break;
588 case 0xe7:
589 opcode = 0xe5;
590 break;
591 case 0xe5:
592 opcode = 0xe7;
593 break;
594 case 0xec:
595 opcode = 0xed;
596 break;
597 case 0xed:
598 opcode = 0xec;
599 break;
600 case 0xee:
601 opcode = 0xef;
602 break;
603 case 0xef:
604 opcode = 0xee;
605 break;
606 default:
607 abort ();
609 fragP->fr_literal[offset + 1] = opcode;
611 /* Create a fixup for the reversed conditional branch. */
612 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
613 fix_new (fragP, fragP->fr_fix + 2, 1,
614 symbol_new (buf, sec, 0, fragP->fr_next),
615 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
617 /* Now create the unconditional branch + fixup to the
618 final target. */
619 fragP->fr_literal[offset + 3] = 0xf4;
620 fragP->fr_literal[offset + 4] = 0xe0;
621 fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
622 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
623 fragP->fr_var = 0;
624 fragP->fr_fix += 8;
626 else if (fragP->fr_subtype == 6)
628 fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
629 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
630 fragP->fr_var = 0;
631 fragP->fr_fix += 3;
633 else if (fragP->fr_subtype == 7)
635 int offset = fragP->fr_fix;
636 fragP->fr_literal[offset] = 0xf4;
637 fragP->fr_literal[offset + 1] = 0xe1;
639 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
640 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
641 fragP->fr_var = 0;
642 fragP->fr_fix += 5;
644 else if (fragP->fr_subtype == 8)
646 fragP->fr_literal[fragP->fr_fix] = 0xea;
647 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
648 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
649 fragP->fr_var = 0;
650 fragP->fr_fix += 2;
652 else if (fragP->fr_subtype == 9)
654 int offset = fragP->fr_fix;
655 fragP->fr_literal[offset] = 0xfc;
657 fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
658 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
659 fragP->fr_var = 0;
660 fragP->fr_fix += 3;
662 else if (fragP->fr_subtype == 10)
664 int offset = fragP->fr_fix;
665 fragP->fr_literal[offset] = 0xf4;
666 fragP->fr_literal[offset + 1] = 0xe0;
668 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
669 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
670 fragP->fr_var = 0;
671 fragP->fr_fix += 5;
673 else
674 abort ();
677 valueT
678 md_section_align (asection *seg, valueT addr)
680 int align = bfd_get_section_alignment (stdoutput, seg);
681 return ((addr + (1 << align) - 1) & (-1 << align));
684 void
685 md_begin (void)
687 char *prev_name = "";
688 register const struct mn10200_opcode *op;
690 mn10200_hash = hash_new ();
692 /* Insert unique names into hash table. The MN10200 instruction set
693 has many identical opcode names that have different opcodes based
694 on the operands. This hash table then provides a quick index to
695 the first opcode with a particular name in the opcode table. */
697 op = mn10200_opcodes;
698 while (op->name)
700 if (strcmp (prev_name, op->name))
702 prev_name = (char *) op->name;
703 hash_insert (mn10200_hash, op->name, (char *) op);
705 op++;
708 /* This is both a simplification (we don't have to write md_apply_fix)
709 and support for future optimizations (branch shortening and similar
710 stuff in the linker. */
711 linkrelax = 1;
714 static unsigned long
715 check_operand (unsigned long insn ATTRIBUTE_UNUSED,
716 const struct mn10200_operand *operand,
717 offsetT val)
719 /* No need to check 24bit or 32bit operands for a bit. */
720 if (operand->bits < 24
721 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
723 long min, max;
724 offsetT test;
726 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
728 max = (1 << (operand->bits - 1)) - 1;
729 min = - (1 << (operand->bits - 1));
731 else
733 max = (1 << operand->bits) - 1;
734 min = 0;
737 test = val;
739 if (test < (offsetT) min || test > (offsetT) max)
740 return 0;
741 else
742 return 1;
744 return 1;
746 /* If while processing a fixup, a reloc really needs to be created
747 Then it is done here. */
749 arelent *
750 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
752 arelent *reloc;
753 reloc = xmalloc (sizeof (arelent));
755 if (fixp->fx_subsy != NULL)
757 if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
758 && S_IS_DEFINED (fixp->fx_subsy))
760 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
761 fixp->fx_subsy = NULL;
763 else
764 /* FIXME: We should try more ways to resolve difference expressions
765 here. At least this is better than silently ignoring the
766 subtrahend. */
767 as_bad_where (fixp->fx_file, fixp->fx_line,
768 _("can't resolve `%s' {%s section} - `%s' {%s section}"),
769 fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
770 segment_name (fixp->fx_addsy
771 ? S_GET_SEGMENT (fixp->fx_addsy)
772 : absolute_section),
773 S_GET_NAME (fixp->fx_subsy),
774 segment_name (S_GET_SEGMENT (fixp->fx_addsy)));
777 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
778 if (reloc->howto == NULL)
780 as_bad_where (fixp->fx_file, fixp->fx_line,
781 _("reloc %d not supported by object file format"),
782 (int) fixp->fx_r_type);
783 return NULL;
785 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
786 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
787 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
788 reloc->addend = fixp->fx_offset;
789 return reloc;
793 md_estimate_size_before_relax (fragS *fragp, asection *seg)
795 if (fragp->fr_subtype == 6
796 && (!S_IS_DEFINED (fragp->fr_symbol)
797 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
798 fragp->fr_subtype = 7;
799 else if (fragp->fr_subtype == 8
800 && (!S_IS_DEFINED (fragp->fr_symbol)
801 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
802 fragp->fr_subtype = 10;
804 if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
805 abort ();
807 return md_relax_table[fragp->fr_subtype].rlx_length;
810 long
811 md_pcrel_from (fixS *fixp)
813 return fixp->fx_frag->fr_address;
816 void
817 md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
819 /* We shouldn't ever get here because linkrelax is nonzero. */
820 abort ();
821 fixP->fx_done = 1;
824 /* Insert an operand value into an instruction. */
826 static void
827 mn10200_insert_operand (unsigned long *insnp,
828 unsigned long *extensionp,
829 const struct mn10200_operand *operand,
830 offsetT val,
831 char *file,
832 unsigned int line,
833 unsigned int shift)
835 /* No need to check 24 or 32bit operands for a bit. */
836 if (operand->bits < 24
837 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
839 long min, max;
840 offsetT test;
842 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
844 max = (1 << (operand->bits - 1)) - 1;
845 min = - (1 << (operand->bits - 1));
847 else
849 max = (1 << operand->bits) - 1;
850 min = 0;
853 test = val;
855 if (test < (offsetT) min || test > (offsetT) max)
856 as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
859 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
861 *insnp |= (((long) val & ((1 << operand->bits) - 1))
862 << (operand->shift + shift));
864 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
865 *insnp |= (((long) val & ((1 << operand->bits) - 1))
866 << (operand->shift + shift + 2));
868 else
870 *extensionp |= (val >> 16) & 0xff;
871 *insnp |= val & 0xffff;
875 void
876 md_assemble (char *str)
878 char *s;
879 struct mn10200_opcode *opcode;
880 struct mn10200_opcode *next_opcode;
881 const unsigned char *opindex_ptr;
882 int next_opindex, relaxable;
883 unsigned long insn, extension, size = 0;
884 char *f;
885 int i;
886 int match;
888 /* Get the opcode. */
889 for (s = str; *s != '\0' && !ISSPACE (*s); s++)
891 if (*s != '\0')
892 *s++ = '\0';
894 /* Find the first opcode with the proper name. */
895 opcode = (struct mn10200_opcode *) hash_find (mn10200_hash, str);
896 if (opcode == NULL)
898 as_bad (_("Unrecognized opcode: `%s'"), str);
899 return;
902 str = s;
903 while (ISSPACE (*str))
904 ++str;
906 input_line_pointer = str;
908 for (;;)
910 const char *errmsg = NULL;
911 int op_idx;
912 char *hold;
913 int extra_shift = 0;
915 relaxable = 0;
916 fc = 0;
917 match = 0;
918 next_opindex = 0;
919 insn = opcode->opcode;
920 extension = 0;
921 for (op_idx = 1, opindex_ptr = opcode->operands;
922 *opindex_ptr != 0;
923 opindex_ptr++, op_idx++)
925 const struct mn10200_operand *operand;
926 expressionS ex;
928 if (next_opindex == 0)
930 operand = &mn10200_operands[*opindex_ptr];
932 else
934 operand = &mn10200_operands[next_opindex];
935 next_opindex = 0;
938 errmsg = NULL;
940 while (*str == ' ' || *str == ',')
941 ++str;
943 if (operand->flags & MN10200_OPERAND_RELAX)
944 relaxable = 1;
946 /* Gather the operand. */
947 hold = input_line_pointer;
948 input_line_pointer = str;
950 if (operand->flags & MN10200_OPERAND_PAREN)
952 if (*input_line_pointer != ')' && *input_line_pointer != '(')
954 input_line_pointer = hold;
955 str = hold;
956 goto error;
958 input_line_pointer++;
959 goto keep_going;
961 /* See if we can match the operands. */
962 else if (operand->flags & MN10200_OPERAND_DREG)
964 if (!data_register_name (&ex))
966 input_line_pointer = hold;
967 str = hold;
968 goto error;
971 else if (operand->flags & MN10200_OPERAND_AREG)
973 if (!address_register_name (&ex))
975 input_line_pointer = hold;
976 str = hold;
977 goto error;
980 else if (operand->flags & MN10200_OPERAND_PSW)
982 char *start = input_line_pointer;
983 char c = get_symbol_end ();
985 if (strcmp (start, "psw") != 0)
987 *input_line_pointer = c;
988 input_line_pointer = hold;
989 str = hold;
990 goto error;
992 *input_line_pointer = c;
993 goto keep_going;
995 else if (operand->flags & MN10200_OPERAND_MDR)
997 char *start = input_line_pointer;
998 char c = get_symbol_end ();
1000 if (strcmp (start, "mdr") != 0)
1002 *input_line_pointer = c;
1003 input_line_pointer = hold;
1004 str = hold;
1005 goto error;
1007 *input_line_pointer = c;
1008 goto keep_going;
1010 else if (data_register_name (&ex))
1012 input_line_pointer = hold;
1013 str = hold;
1014 goto error;
1016 else if (address_register_name (&ex))
1018 input_line_pointer = hold;
1019 str = hold;
1020 goto error;
1022 else if (other_register_name (&ex))
1024 input_line_pointer = hold;
1025 str = hold;
1026 goto error;
1028 else if (*str == ')' || *str == '(')
1030 input_line_pointer = hold;
1031 str = hold;
1032 goto error;
1034 else
1036 expression (&ex);
1039 switch (ex.X_op)
1041 case O_illegal:
1042 errmsg = _("illegal operand");
1043 goto error;
1044 case O_absent:
1045 errmsg = _("missing operand");
1046 goto error;
1047 case O_register:
1048 if ((operand->flags
1049 & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
1051 input_line_pointer = hold;
1052 str = hold;
1053 goto error;
1056 if (opcode->format == FMT_2 || opcode->format == FMT_5)
1057 extra_shift = 8;
1058 else if (opcode->format == FMT_3 || opcode->format == FMT_6
1059 || opcode->format == FMT_7)
1060 extra_shift = 16;
1061 else
1062 extra_shift = 0;
1064 mn10200_insert_operand (&insn, &extension, operand,
1065 ex.X_add_number, NULL,
1066 0, extra_shift);
1068 break;
1070 case O_constant:
1071 /* If this operand can be promoted, and it doesn't
1072 fit into the allocated bitfield for this insn,
1073 then promote it (ie this opcode does not match). */
1074 if (operand->flags
1075 & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
1076 && !check_operand (insn, operand, ex.X_add_number))
1078 input_line_pointer = hold;
1079 str = hold;
1080 goto error;
1083 mn10200_insert_operand (&insn, &extension, operand,
1084 ex.X_add_number, NULL,
1085 0, 0);
1086 break;
1088 default:
1089 /* If this operand can be promoted, then this opcode didn't
1090 match since we can't know if it needed promotion! */
1091 if (operand->flags & MN10200_OPERAND_PROMOTE)
1093 input_line_pointer = hold;
1094 str = hold;
1095 goto error;
1098 /* We need to generate a fixup for this expression. */
1099 if (fc >= MAX_INSN_FIXUPS)
1100 as_fatal (_("too many fixups"));
1101 fixups[fc].exp = ex;
1102 fixups[fc].opindex = *opindex_ptr;
1103 fixups[fc].reloc = BFD_RELOC_UNUSED;
1104 ++fc;
1105 break;
1108 keep_going:
1109 str = input_line_pointer;
1110 input_line_pointer = hold;
1112 while (*str == ' ' || *str == ',')
1113 ++str;
1117 /* Make sure we used all the operands! */
1118 if (*str != ',')
1119 match = 1;
1121 error:
1122 if (match == 0)
1124 next_opcode = opcode + 1;
1125 if (!strcmp (next_opcode->name, opcode->name))
1127 opcode = next_opcode;
1128 continue;
1131 as_bad ("%s", errmsg);
1132 return;
1134 break;
1137 while (ISSPACE (*str))
1138 ++str;
1140 if (*str != '\0')
1141 as_bad (_("junk at end of line: `%s'"), str);
1143 input_line_pointer = str;
1145 if (opcode->format == FMT_1)
1146 size = 1;
1147 else if (opcode->format == FMT_2 || opcode->format == FMT_4)
1148 size = 2;
1149 else if (opcode->format == FMT_3 || opcode->format == FMT_5)
1150 size = 3;
1151 else if (opcode->format == FMT_6)
1152 size = 4;
1153 else if (opcode->format == FMT_7)
1154 size = 5;
1155 else
1156 abort ();
1158 /* Write out the instruction. */
1159 dwarf2_emit_insn (0);
1160 if (relaxable && fc > 0)
1162 /* On a 64-bit host the size of an 'int' is not the same
1163 as the size of a pointer, so we need a union to convert
1164 the opindex field of the fr_cgen structure into a char *
1165 so that it can be stored in the frag. We do not have
1166 to worry about loosing accuracy as we are not going to
1167 be even close to the 32bit limit of the int. */
1168 union
1170 int opindex;
1171 char * ptr;
1173 opindex_converter;
1174 int type;
1176 /* bCC */
1177 if (size == 2 && opcode->opcode != 0xfc0000)
1179 /* Handle bra specially. Basically treat it like jmp so
1180 that we automatically handle 8, 16 and 32 bit offsets
1181 correctly as well as jumps to an undefined address.
1183 It is also important to not treat it like other bCC
1184 instructions since the long forms of bra is different
1185 from other bCC instructions. */
1186 if (opcode->opcode == 0xea00)
1187 type = 8;
1188 else
1189 type = 0;
1191 /* jsr */
1192 else if (size == 3 && opcode->opcode == 0xfd0000)
1193 type = 6;
1194 /* jmp */
1195 else if (size == 3 && opcode->opcode == 0xfc0000)
1196 type = 8;
1197 /* bCCx */
1198 else
1199 type = 3;
1201 opindex_converter.opindex = fixups[0].opindex;
1202 f = frag_var (rs_machine_dependent, 8, 8 - size, type,
1203 fixups[0].exp.X_add_symbol,
1204 fixups[0].exp.X_add_number,
1205 opindex_converter.ptr);
1206 number_to_chars_bigendian (f, insn, size);
1207 if (8 - size > 4)
1209 number_to_chars_bigendian (f + size, 0, 4);
1210 number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
1212 else
1213 number_to_chars_bigendian (f + size, 0, 8 - size);
1215 else
1217 f = frag_more (size);
1219 /* Oh, what a mess. The instruction is in big endian format, but
1220 16 and 24bit immediates are little endian! */
1221 if (opcode->format == FMT_3)
1223 number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
1224 number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
1226 else if (opcode->format == FMT_6)
1228 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1229 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1231 else if (opcode->format == FMT_7)
1233 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1234 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1235 number_to_chars_littleendian (f + 4, extension & 0xff, 1);
1237 else
1238 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
1240 /* Create any fixups. */
1241 for (i = 0; i < fc; i++)
1243 const struct mn10200_operand *operand;
1244 int reloc_size;
1246 operand = &mn10200_operands[fixups[i].opindex];
1247 if (fixups[i].reloc != BFD_RELOC_UNUSED)
1249 reloc_howto_type *reloc_howto;
1250 int offset;
1251 fixS *fixP;
1253 reloc_howto = bfd_reloc_type_lookup (stdoutput,
1254 fixups[i].reloc);
1256 if (!reloc_howto)
1257 abort ();
1259 reloc_size = bfd_get_reloc_size (reloc_howto);
1261 if (reloc_size < 1 || reloc_size > 4)
1262 abort ();
1264 offset = 4 - reloc_size;
1265 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1266 reloc_size,
1267 &fixups[i].exp,
1268 reloc_howto->pc_relative,
1269 fixups[i].reloc);
1271 /* PC-relative offsets are from the first byte of the
1272 next instruction, not from the start of the current
1273 instruction. */
1274 if (reloc_howto->pc_relative)
1275 fixP->fx_offset += reloc_size;
1277 else
1279 int reloc, pcrel, offset;
1280 fixS *fixP;
1282 reloc = BFD_RELOC_NONE;
1283 /* How big is the reloc? Remember SPLIT relocs are
1284 implicitly 32bits. */
1285 reloc_size = operand->bits;
1287 offset = size - reloc_size / 8;
1289 /* Is the reloc pc-relative? */
1290 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
1292 /* Choose a proper BFD relocation type. */
1293 if (pcrel)
1295 if (reloc_size == 8)
1296 reloc = BFD_RELOC_8_PCREL;
1297 else if (reloc_size == 24)
1298 reloc = BFD_RELOC_24_PCREL;
1299 else
1300 abort ();
1302 else
1304 if (reloc_size == 32)
1305 reloc = BFD_RELOC_32;
1306 else if (reloc_size == 16)
1307 reloc = BFD_RELOC_16;
1308 else if (reloc_size == 8)
1309 reloc = BFD_RELOC_8;
1310 else if (reloc_size == 24)
1311 reloc = BFD_RELOC_24;
1312 else
1313 abort ();
1316 /* Convert the size of the reloc into what fix_new_exp
1317 wants. */
1318 reloc_size = reloc_size / 8;
1319 if (reloc_size == 8)
1320 reloc_size = 0;
1321 else if (reloc_size == 16)
1322 reloc_size = 1;
1323 else if (reloc_size == 32 || reloc_size == 24)
1324 reloc_size = 2;
1326 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1327 reloc_size, &fixups[i].exp, pcrel,
1328 ((bfd_reloc_code_real_type) reloc));
1330 /* PC-relative offsets are from the first byte of the
1331 next instruction, not from the start of the current
1332 instruction. */
1333 if (pcrel)
1334 fixP->fx_offset += size;