Add expected failures for CR16 tests
[deliverable/binutils-gdb.git] / gas / config / tc-mn10200.c
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 Free Software Foundation, Inc.
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 3, 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, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #include "as.h"
23 #include "safe-ctype.h"
24 #include "subsegs.h"
25 #include "opcode/mn10200.h"
26 \f
27 /* Structure to hold information about predefined registers. */
28 struct reg_name
29 {
30 const char *name;
31 int value;
32 };
33
34 /* Generic assembler global variables which must be defined by all
35 targets. */
36
37 /* Characters which always start a comment. */
38 const char comment_chars[] = "#";
39
40 /* Characters which start a comment at the beginning of a line. */
41 const char line_comment_chars[] = ";#";
42
43 /* Characters which may be used to separate multiple commands on a
44 single line. */
45 const char line_separator_chars[] = ";";
46
47 /* Characters which are used to indicate an exponent in a floating
48 point number. */
49 const char EXP_CHARS[] = "eE";
50
51 /* Characters which mean that a number is a floating point constant,
52 as in 0d1.0. */
53 const char FLT_CHARS[] = "dD";
54 \f
55 const relax_typeS md_relax_table[] =
56 {
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},
72
73 };
74
75
76 /* Fixups. */
77 #define MAX_INSN_FIXUPS 5
78
79 struct mn10200_fixup
80 {
81 expressionS exp;
82 int opindex;
83 bfd_reloc_code_real_type reloc;
84 };
85
86 struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
87 static int fc;
88 \f
89 const char *md_shortopts = "";
90
91 struct option md_longopts[] =
92 {
93 {NULL, no_argument, NULL, 0}
94 };
95
96 size_t md_longopts_size = sizeof (md_longopts);
97
98 /* The target specific pseudo-ops which we support. */
99 const pseudo_typeS md_pseudo_table[] =
100 {
101 { NULL, NULL, 0 }
102 };
103
104 /* Opcode hash table. */
105 static struct hash_control *mn10200_hash;
106
107 /* This table is sorted. Suitable for searching by a binary search. */
108 static const struct reg_name data_registers[] =
109 {
110 { "d0", 0 },
111 { "d1", 1 },
112 { "d2", 2 },
113 { "d3", 3 },
114 };
115 #define DATA_REG_NAME_CNT \
116 (sizeof (data_registers) / sizeof (struct reg_name))
117
118 static const struct reg_name address_registers[] =
119 {
120 { "a0", 0 },
121 { "a1", 1 },
122 { "a2", 2 },
123 { "a3", 3 },
124 };
125 #define ADDRESS_REG_NAME_CNT \
126 (sizeof (address_registers) / sizeof (struct reg_name))
127
128 static const struct reg_name other_registers[] =
129 {
130 { "mdr", 0 },
131 { "psw", 0 },
132 };
133 #define OTHER_REG_NAME_CNT \
134 (sizeof (other_registers) / sizeof (struct reg_name))
135
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. */
139
140 static int
141 reg_name_search (const struct reg_name *regs,
142 int regcount,
143 const char *name)
144 {
145 int middle, low, high;
146 int cmp;
147
148 low = 0;
149 high = regcount - 1;
150
151 do
152 {
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;
161 }
162 while (low <= high);
163 return -1;
164 }
165
166 /* Summary of register_name().
167
168 in: Input_line_pointer points to 1st char of operand.
169
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. */
175
176 static bfd_boolean
177 data_register_name (expressionS *expressionP)
178 {
179 int reg_number;
180 char *name;
181 char *start;
182 char c;
183
184 /* Find the spelling of the operand. */
185 start = name = input_line_pointer;
186
187 c = get_symbol_end ();
188 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
189
190 /* Put back the delimiting char. */
191 *input_line_pointer = c;
192
193 /* Look to see if it's in the register table. */
194 if (reg_number >= 0)
195 {
196 expressionP->X_op = O_register;
197 expressionP->X_add_number = reg_number;
198
199 /* Make the rest nice. */
200 expressionP->X_add_symbol = NULL;
201 expressionP->X_op_symbol = NULL;
202
203 return TRUE;
204 }
205
206 /* Reset the line as if we had not done anything. */
207 input_line_pointer = start;
208 return FALSE;
209 }
210
211 /* Summary of register_name().
212
213 in: Input_line_pointer points to 1st char of operand.
214
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. */
220
221 static bfd_boolean
222 address_register_name (expressionS *expressionP)
223 {
224 int reg_number;
225 char *name;
226 char *start;
227 char c;
228
229 /* Find the spelling of the operand. */
230 start = name = input_line_pointer;
231
232 c = get_symbol_end ();
233 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
234
235 /* Put back the delimiting char. */
236 *input_line_pointer = c;
237
238 /* Look to see if it's in the register table. */
239 if (reg_number >= 0)
240 {
241 expressionP->X_op = O_register;
242 expressionP->X_add_number = reg_number;
243
244 /* Make the rest nice. */
245 expressionP->X_add_symbol = NULL;
246 expressionP->X_op_symbol = NULL;
247
248 return TRUE;
249 }
250
251 /* Reset the line as if we had not done anything. */
252 input_line_pointer = start;
253 return FALSE;
254 }
255
256 /* Summary of register_name().
257
258 in: Input_line_pointer points to 1st char of operand.
259
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. */
265
266 static bfd_boolean
267 other_register_name (expressionS *expressionP)
268 {
269 int reg_number;
270 char *name;
271 char *start;
272 char c;
273
274 /* Find the spelling of the operand. */
275 start = name = input_line_pointer;
276
277 c = get_symbol_end ();
278 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
279
280 /* Put back the delimiting char. */
281 *input_line_pointer = c;
282
283 /* Look to see if it's in the register table. */
284 if (reg_number >= 0)
285 {
286 expressionP->X_op = O_register;
287 expressionP->X_add_number = reg_number;
288
289 /* Make the rest nice. */
290 expressionP->X_add_symbol = NULL;
291 expressionP->X_op_symbol = NULL;
292
293 return TRUE;
294 }
295
296 /* Reset the line as if we had not done anything. */
297 input_line_pointer = start;
298 return FALSE;
299 }
300
301 void
302 md_show_usage (FILE *stream)
303 {
304 fprintf (stream, _("MN10200 options:\n\
305 none yet\n"));
306 }
307
308 int
309 md_parse_option (int c ATTRIBUTE_UNUSED,
310 char *arg ATTRIBUTE_UNUSED)
311 {
312 return 0;
313 }
314
315 symbolS *
316 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
317 {
318 return 0;
319 }
320
321 char *
322 md_atof (int type, char *litp, int *sizep)
323 {
324 int prec;
325 LITTLENUM_TYPE words[4];
326 char *t;
327 int i;
328
329 switch (type)
330 {
331 case 'f':
332 prec = 2;
333 break;
334
335 case 'd':
336 prec = 4;
337 break;
338
339 default:
340 *sizep = 0;
341 return _("bad call to md_atof");
342 }
343
344 t = atof_ieee (input_line_pointer, type, words);
345 if (t)
346 input_line_pointer = t;
347
348 *sizep = prec * 2;
349
350 for (i = prec - 1; i >= 0; i--)
351 {
352 md_number_to_chars (litp, (valueT) words[i], 2);
353 litp += 2;
354 }
355
356 return NULL;
357 }
358
359 void
360 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
361 asection *sec,
362 fragS *fragP)
363 {
364 static unsigned long label_count = 0;
365 char buf[40];
366
367 subseg_change (sec, 0);
368 if (fragP->fr_subtype == 0)
369 {
370 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
371 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
372 fragP->fr_var = 0;
373 fragP->fr_fix += 2;
374 }
375 else if (fragP->fr_subtype == 1)
376 {
377 /* Reverse the condition of the first branch. */
378 int offset = fragP->fr_fix;
379 int opcode = fragP->fr_literal[offset] & 0xff;
380
381 switch (opcode)
382 {
383 case 0xe8:
384 opcode = 0xe9;
385 break;
386 case 0xe9:
387 opcode = 0xe8;
388 break;
389 case 0xe0:
390 opcode = 0xe2;
391 break;
392 case 0xe2:
393 opcode = 0xe0;
394 break;
395 case 0xe3:
396 opcode = 0xe1;
397 break;
398 case 0xe1:
399 opcode = 0xe3;
400 break;
401 case 0xe4:
402 opcode = 0xe6;
403 break;
404 case 0xe6:
405 opcode = 0xe4;
406 break;
407 case 0xe7:
408 opcode = 0xe5;
409 break;
410 case 0xe5:
411 opcode = 0xe7;
412 break;
413 default:
414 abort ();
415 }
416 fragP->fr_literal[offset] = opcode;
417
418 /* Create a fixup for the reversed conditional branch. */
419 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
420 fix_new (fragP, fragP->fr_fix + 1, 1,
421 symbol_new (buf, sec, 0, fragP->fr_next),
422 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
423
424 /* Now create the unconditional branch + fixup to the
425 final target. */
426 fragP->fr_literal[offset + 2] = 0xfc;
427 fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
428 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
429 fragP->fr_var = 0;
430 fragP->fr_fix += 5;
431 }
432 else if (fragP->fr_subtype == 2)
433 {
434 /* Reverse the condition of the first branch. */
435 int offset = fragP->fr_fix;
436 int opcode = fragP->fr_literal[offset] & 0xff;
437
438 switch (opcode)
439 {
440 case 0xe8:
441 opcode = 0xe9;
442 break;
443 case 0xe9:
444 opcode = 0xe8;
445 break;
446 case 0xe0:
447 opcode = 0xe2;
448 break;
449 case 0xe2:
450 opcode = 0xe0;
451 break;
452 case 0xe3:
453 opcode = 0xe1;
454 break;
455 case 0xe1:
456 opcode = 0xe3;
457 break;
458 case 0xe4:
459 opcode = 0xe6;
460 break;
461 case 0xe6:
462 opcode = 0xe4;
463 break;
464 case 0xe7:
465 opcode = 0xe5;
466 break;
467 case 0xe5:
468 opcode = 0xe7;
469 break;
470 default:
471 abort ();
472 }
473 fragP->fr_literal[offset] = opcode;
474
475 /* Create a fixup for the reversed conditional branch. */
476 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
477 fix_new (fragP, fragP->fr_fix + 1, 1,
478 symbol_new (buf, sec, 0, fragP->fr_next),
479 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
480
481 /* Now create the unconditional branch + fixup to the
482 final target. */
483 fragP->fr_literal[offset + 2] = 0xf4;
484 fragP->fr_literal[offset + 3] = 0xe0;
485 fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
486 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
487 fragP->fr_var = 0;
488 fragP->fr_fix += 7;
489 }
490 else if (fragP->fr_subtype == 3)
491 {
492 fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
493 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
494 fragP->fr_var = 0;
495 fragP->fr_fix += 3;
496 }
497 else if (fragP->fr_subtype == 4)
498 {
499 /* Reverse the condition of the first branch. */
500 int offset = fragP->fr_fix;
501 int opcode = fragP->fr_literal[offset + 1] & 0xff;
502
503 switch (opcode)
504 {
505 case 0xfc:
506 opcode = 0xfd;
507 break;
508 case 0xfd:
509 opcode = 0xfc;
510 break;
511 case 0xfe:
512 opcode = 0xff;
513 break;
514 case 0xff:
515 opcode = 0xfe;
516 case 0xe8:
517 opcode = 0xe9;
518 break;
519 case 0xe9:
520 opcode = 0xe8;
521 break;
522 case 0xe0:
523 opcode = 0xe2;
524 break;
525 case 0xe2:
526 opcode = 0xe0;
527 break;
528 case 0xe3:
529 opcode = 0xe1;
530 break;
531 case 0xe1:
532 opcode = 0xe3;
533 break;
534 case 0xe4:
535 opcode = 0xe6;
536 break;
537 case 0xe6:
538 opcode = 0xe4;
539 break;
540 case 0xe7:
541 opcode = 0xe5;
542 break;
543 case 0xe5:
544 opcode = 0xe7;
545 break;
546 case 0xec:
547 opcode = 0xed;
548 break;
549 case 0xed:
550 opcode = 0xec;
551 break;
552 case 0xee:
553 opcode = 0xef;
554 break;
555 case 0xef:
556 opcode = 0xee;
557 break;
558 default:
559 abort ();
560 }
561 fragP->fr_literal[offset + 1] = opcode;
562
563 /* Create a fixup for the reversed conditional branch. */
564 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
565 fix_new (fragP, fragP->fr_fix + 2, 1,
566 symbol_new (buf, sec, 0, fragP->fr_next),
567 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
568
569 /* Now create the unconditional branch + fixup to the
570 final target. */
571 fragP->fr_literal[offset + 3] = 0xfc;
572 fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
573 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
574 fragP->fr_var = 0;
575 fragP->fr_fix += 6;
576 }
577 else if (fragP->fr_subtype == 5)
578 {
579 /* Reverse the condition of the first branch. */
580 int offset = fragP->fr_fix;
581 int opcode = fragP->fr_literal[offset + 1] & 0xff;
582
583 switch (opcode)
584 {
585 case 0xfc:
586 opcode = 0xfd;
587 break;
588 case 0xfd:
589 opcode = 0xfc;
590 break;
591 case 0xfe:
592 opcode = 0xff;
593 break;
594 case 0xff:
595 opcode = 0xfe;
596 case 0xe8:
597 opcode = 0xe9;
598 break;
599 case 0xe9:
600 opcode = 0xe8;
601 break;
602 case 0xe0:
603 opcode = 0xe2;
604 break;
605 case 0xe2:
606 opcode = 0xe0;
607 break;
608 case 0xe3:
609 opcode = 0xe1;
610 break;
611 case 0xe1:
612 opcode = 0xe3;
613 break;
614 case 0xe4:
615 opcode = 0xe6;
616 break;
617 case 0xe6:
618 opcode = 0xe4;
619 break;
620 case 0xe7:
621 opcode = 0xe5;
622 break;
623 case 0xe5:
624 opcode = 0xe7;
625 break;
626 case 0xec:
627 opcode = 0xed;
628 break;
629 case 0xed:
630 opcode = 0xec;
631 break;
632 case 0xee:
633 opcode = 0xef;
634 break;
635 case 0xef:
636 opcode = 0xee;
637 break;
638 default:
639 abort ();
640 }
641 fragP->fr_literal[offset + 1] = opcode;
642
643 /* Create a fixup for the reversed conditional branch. */
644 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
645 fix_new (fragP, fragP->fr_fix + 2, 1,
646 symbol_new (buf, sec, 0, fragP->fr_next),
647 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
648
649 /* Now create the unconditional branch + fixup to the
650 final target. */
651 fragP->fr_literal[offset + 3] = 0xf4;
652 fragP->fr_literal[offset + 4] = 0xe0;
653 fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
654 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
655 fragP->fr_var = 0;
656 fragP->fr_fix += 8;
657 }
658 else if (fragP->fr_subtype == 6)
659 {
660 fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
661 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
662 fragP->fr_var = 0;
663 fragP->fr_fix += 3;
664 }
665 else if (fragP->fr_subtype == 7)
666 {
667 int offset = fragP->fr_fix;
668 fragP->fr_literal[offset] = 0xf4;
669 fragP->fr_literal[offset + 1] = 0xe1;
670
671 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
672 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
673 fragP->fr_var = 0;
674 fragP->fr_fix += 5;
675 }
676 else if (fragP->fr_subtype == 8)
677 {
678 fragP->fr_literal[fragP->fr_fix] = 0xea;
679 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
680 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
681 fragP->fr_var = 0;
682 fragP->fr_fix += 2;
683 }
684 else if (fragP->fr_subtype == 9)
685 {
686 int offset = fragP->fr_fix;
687 fragP->fr_literal[offset] = 0xfc;
688
689 fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
690 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
691 fragP->fr_var = 0;
692 fragP->fr_fix += 3;
693 }
694 else if (fragP->fr_subtype == 10)
695 {
696 int offset = fragP->fr_fix;
697 fragP->fr_literal[offset] = 0xf4;
698 fragP->fr_literal[offset + 1] = 0xe0;
699
700 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
701 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
702 fragP->fr_var = 0;
703 fragP->fr_fix += 5;
704 }
705 else
706 abort ();
707 }
708
709 valueT
710 md_section_align (asection *seg, valueT addr)
711 {
712 int align = bfd_get_section_alignment (stdoutput, seg);
713 return ((addr + (1 << align) - 1) & (-1 << align));
714 }
715
716 void
717 md_begin (void)
718 {
719 char *prev_name = "";
720 register const struct mn10200_opcode *op;
721
722 mn10200_hash = hash_new ();
723
724 /* Insert unique names into hash table. The MN10200 instruction set
725 has many identical opcode names that have different opcodes based
726 on the operands. This hash table then provides a quick index to
727 the first opcode with a particular name in the opcode table. */
728
729 op = mn10200_opcodes;
730 while (op->name)
731 {
732 if (strcmp (prev_name, op->name))
733 {
734 prev_name = (char *) op->name;
735 hash_insert (mn10200_hash, op->name, (char *) op);
736 }
737 op++;
738 }
739
740 /* This is both a simplification (we don't have to write md_apply_fix)
741 and support for future optimizations (branch shortening and similar
742 stuff in the linker. */
743 linkrelax = 1;
744 }
745
746 static unsigned long
747 check_operand (unsigned long insn ATTRIBUTE_UNUSED,
748 const struct mn10200_operand *operand,
749 offsetT val)
750 {
751 /* No need to check 24bit or 32bit operands for a bit. */
752 if (operand->bits < 24
753 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
754 {
755 long min, max;
756 offsetT test;
757
758 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
759 {
760 max = (1 << (operand->bits - 1)) - 1;
761 min = - (1 << (operand->bits - 1));
762 }
763 else
764 {
765 max = (1 << operand->bits) - 1;
766 min = 0;
767 }
768
769 test = val;
770
771 if (test < (offsetT) min || test > (offsetT) max)
772 return 0;
773 else
774 return 1;
775 }
776 return 1;
777 }
778 /* If while processing a fixup, a reloc really needs to be created
779 Then it is done here. */
780
781 arelent *
782 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
783 {
784 arelent *reloc;
785 reloc = xmalloc (sizeof (arelent));
786
787 if (fixp->fx_subsy != NULL)
788 {
789 if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
790 && S_IS_DEFINED (fixp->fx_subsy))
791 {
792 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
793 fixp->fx_subsy = NULL;
794 }
795 else
796 /* FIXME: We should try more ways to resolve difference expressions
797 here. At least this is better than silently ignoring the
798 subtrahend. */
799 as_bad_where (fixp->fx_file, fixp->fx_line,
800 _("can't resolve `%s' {%s section} - `%s' {%s section}"),
801 fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
802 segment_name (fixp->fx_addsy
803 ? S_GET_SEGMENT (fixp->fx_addsy)
804 : absolute_section),
805 S_GET_NAME (fixp->fx_subsy),
806 segment_name (S_GET_SEGMENT (fixp->fx_addsy)));
807 }
808
809 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
810 if (reloc->howto == NULL)
811 {
812 as_bad_where (fixp->fx_file, fixp->fx_line,
813 _("reloc %d not supported by object file format"),
814 (int) fixp->fx_r_type);
815 return NULL;
816 }
817 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
818 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
819 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
820 reloc->addend = fixp->fx_offset;
821 return reloc;
822 }
823
824 int
825 md_estimate_size_before_relax (fragS *fragp, asection *seg)
826 {
827 if (fragp->fr_subtype == 6
828 && (!S_IS_DEFINED (fragp->fr_symbol)
829 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
830 fragp->fr_subtype = 7;
831 else if (fragp->fr_subtype == 8
832 && (!S_IS_DEFINED (fragp->fr_symbol)
833 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
834 fragp->fr_subtype = 10;
835
836 if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
837 abort ();
838
839 return md_relax_table[fragp->fr_subtype].rlx_length;
840 }
841
842 long
843 md_pcrel_from (fixS *fixp)
844 {
845 return fixp->fx_frag->fr_address;
846 }
847
848 void
849 md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
850 {
851 /* We shouldn't ever get here because linkrelax is nonzero. */
852 abort ();
853 fixP->fx_done = 1;
854 }
855
856 /* Insert an operand value into an instruction. */
857
858 static void
859 mn10200_insert_operand (unsigned long *insnp,
860 unsigned long *extensionp,
861 const struct mn10200_operand *operand,
862 offsetT val,
863 char *file,
864 unsigned int line,
865 unsigned int shift)
866 {
867 /* No need to check 24 or 32bit operands for a bit. */
868 if (operand->bits < 24
869 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
870 {
871 long min, max;
872 offsetT test;
873
874 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
875 {
876 max = (1 << (operand->bits - 1)) - 1;
877 min = - (1 << (operand->bits - 1));
878 }
879 else
880 {
881 max = (1 << operand->bits) - 1;
882 min = 0;
883 }
884
885 test = val;
886
887 if (test < (offsetT) min || test > (offsetT) max)
888 as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
889 }
890
891 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
892 {
893 *insnp |= (((long) val & ((1 << operand->bits) - 1))
894 << (operand->shift + shift));
895
896 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
897 *insnp |= (((long) val & ((1 << operand->bits) - 1))
898 << (operand->shift + shift + 2));
899 }
900 else
901 {
902 *extensionp |= (val >> 16) & 0xff;
903 *insnp |= val & 0xffff;
904 }
905 }
906
907 void
908 md_assemble (char *str)
909 {
910 char *s;
911 struct mn10200_opcode *opcode;
912 struct mn10200_opcode *next_opcode;
913 const unsigned char *opindex_ptr;
914 int next_opindex, relaxable;
915 unsigned long insn, extension, size = 0;
916 char *f;
917 int i;
918 int match;
919
920 /* Get the opcode. */
921 for (s = str; *s != '\0' && !ISSPACE (*s); s++)
922 ;
923 if (*s != '\0')
924 *s++ = '\0';
925
926 /* Find the first opcode with the proper name. */
927 opcode = (struct mn10200_opcode *) hash_find (mn10200_hash, str);
928 if (opcode == NULL)
929 {
930 as_bad (_("Unrecognized opcode: `%s'"), str);
931 return;
932 }
933
934 str = s;
935 while (ISSPACE (*str))
936 ++str;
937
938 input_line_pointer = str;
939
940 for (;;)
941 {
942 const char *errmsg = NULL;
943 int op_idx;
944 char *hold;
945 int extra_shift = 0;
946
947 relaxable = 0;
948 fc = 0;
949 match = 0;
950 next_opindex = 0;
951 insn = opcode->opcode;
952 extension = 0;
953 for (op_idx = 1, opindex_ptr = opcode->operands;
954 *opindex_ptr != 0;
955 opindex_ptr++, op_idx++)
956 {
957 const struct mn10200_operand *operand;
958 expressionS ex;
959
960 if (next_opindex == 0)
961 {
962 operand = &mn10200_operands[*opindex_ptr];
963 }
964 else
965 {
966 operand = &mn10200_operands[next_opindex];
967 next_opindex = 0;
968 }
969
970 errmsg = NULL;
971
972 while (*str == ' ' || *str == ',')
973 ++str;
974
975 if (operand->flags & MN10200_OPERAND_RELAX)
976 relaxable = 1;
977
978 /* Gather the operand. */
979 hold = input_line_pointer;
980 input_line_pointer = str;
981
982 if (operand->flags & MN10200_OPERAND_PAREN)
983 {
984 if (*input_line_pointer != ')' && *input_line_pointer != '(')
985 {
986 input_line_pointer = hold;
987 str = hold;
988 goto error;
989 }
990 input_line_pointer++;
991 goto keep_going;
992 }
993 /* See if we can match the operands. */
994 else if (operand->flags & MN10200_OPERAND_DREG)
995 {
996 if (!data_register_name (&ex))
997 {
998 input_line_pointer = hold;
999 str = hold;
1000 goto error;
1001 }
1002 }
1003 else if (operand->flags & MN10200_OPERAND_AREG)
1004 {
1005 if (!address_register_name (&ex))
1006 {
1007 input_line_pointer = hold;
1008 str = hold;
1009 goto error;
1010 }
1011 }
1012 else if (operand->flags & MN10200_OPERAND_PSW)
1013 {
1014 char *start = input_line_pointer;
1015 char c = get_symbol_end ();
1016
1017 if (strcmp (start, "psw") != 0)
1018 {
1019 *input_line_pointer = c;
1020 input_line_pointer = hold;
1021 str = hold;
1022 goto error;
1023 }
1024 *input_line_pointer = c;
1025 goto keep_going;
1026 }
1027 else if (operand->flags & MN10200_OPERAND_MDR)
1028 {
1029 char *start = input_line_pointer;
1030 char c = get_symbol_end ();
1031
1032 if (strcmp (start, "mdr") != 0)
1033 {
1034 *input_line_pointer = c;
1035 input_line_pointer = hold;
1036 str = hold;
1037 goto error;
1038 }
1039 *input_line_pointer = c;
1040 goto keep_going;
1041 }
1042 else if (data_register_name (&ex))
1043 {
1044 input_line_pointer = hold;
1045 str = hold;
1046 goto error;
1047 }
1048 else if (address_register_name (&ex))
1049 {
1050 input_line_pointer = hold;
1051 str = hold;
1052 goto error;
1053 }
1054 else if (other_register_name (&ex))
1055 {
1056 input_line_pointer = hold;
1057 str = hold;
1058 goto error;
1059 }
1060 else if (*str == ')' || *str == '(')
1061 {
1062 input_line_pointer = hold;
1063 str = hold;
1064 goto error;
1065 }
1066 else
1067 {
1068 expression (&ex);
1069 }
1070
1071 switch (ex.X_op)
1072 {
1073 case O_illegal:
1074 errmsg = _("illegal operand");
1075 goto error;
1076 case O_absent:
1077 errmsg = _("missing operand");
1078 goto error;
1079 case O_register:
1080 if ((operand->flags
1081 & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
1082 {
1083 input_line_pointer = hold;
1084 str = hold;
1085 goto error;
1086 }
1087
1088 if (opcode->format == FMT_2 || opcode->format == FMT_5)
1089 extra_shift = 8;
1090 else if (opcode->format == FMT_3 || opcode->format == FMT_6
1091 || opcode->format == FMT_7)
1092 extra_shift = 16;
1093 else
1094 extra_shift = 0;
1095
1096 mn10200_insert_operand (&insn, &extension, operand,
1097 ex.X_add_number, NULL,
1098 0, extra_shift);
1099
1100 break;
1101
1102 case O_constant:
1103 /* If this operand can be promoted, and it doesn't
1104 fit into the allocated bitfield for this insn,
1105 then promote it (ie this opcode does not match). */
1106 if (operand->flags
1107 & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
1108 && !check_operand (insn, operand, ex.X_add_number))
1109 {
1110 input_line_pointer = hold;
1111 str = hold;
1112 goto error;
1113 }
1114
1115 mn10200_insert_operand (&insn, &extension, operand,
1116 ex.X_add_number, NULL,
1117 0, 0);
1118 break;
1119
1120 default:
1121 /* If this operand can be promoted, then this opcode didn't
1122 match since we can't know if it needed promotion! */
1123 if (operand->flags & MN10200_OPERAND_PROMOTE)
1124 {
1125 input_line_pointer = hold;
1126 str = hold;
1127 goto error;
1128 }
1129
1130 /* We need to generate a fixup for this expression. */
1131 if (fc >= MAX_INSN_FIXUPS)
1132 as_fatal (_("too many fixups"));
1133 fixups[fc].exp = ex;
1134 fixups[fc].opindex = *opindex_ptr;
1135 fixups[fc].reloc = BFD_RELOC_UNUSED;
1136 ++fc;
1137 break;
1138 }
1139
1140 keep_going:
1141 str = input_line_pointer;
1142 input_line_pointer = hold;
1143
1144 while (*str == ' ' || *str == ',')
1145 ++str;
1146
1147 }
1148
1149 /* Make sure we used all the operands! */
1150 if (*str != ',')
1151 match = 1;
1152
1153 error:
1154 if (match == 0)
1155 {
1156 next_opcode = opcode + 1;
1157 if (!strcmp (next_opcode->name, opcode->name))
1158 {
1159 opcode = next_opcode;
1160 continue;
1161 }
1162
1163 as_bad ("%s", errmsg);
1164 return;
1165 }
1166 break;
1167 }
1168
1169 while (ISSPACE (*str))
1170 ++str;
1171
1172 if (*str != '\0')
1173 as_bad (_("junk at end of line: `%s'"), str);
1174
1175 input_line_pointer = str;
1176
1177 if (opcode->format == FMT_1)
1178 size = 1;
1179 else if (opcode->format == FMT_2 || opcode->format == FMT_4)
1180 size = 2;
1181 else if (opcode->format == FMT_3 || opcode->format == FMT_5)
1182 size = 3;
1183 else if (opcode->format == FMT_6)
1184 size = 4;
1185 else if (opcode->format == FMT_7)
1186 size = 5;
1187 else
1188 abort ();
1189
1190 /* Write out the instruction. */
1191 if (relaxable && fc > 0)
1192 {
1193 /* On a 64-bit host the size of an 'int' is not the same
1194 as the size of a pointer, so we need a union to convert
1195 the opindex field of the fr_cgen structure into a char *
1196 so that it can be stored in the frag. We do not have
1197 to worry about loosing accuracy as we are not going to
1198 be even close to the 32bit limit of the int. */
1199 union
1200 {
1201 int opindex;
1202 char * ptr;
1203 }
1204 opindex_converter;
1205 int type;
1206
1207 /* bCC */
1208 if (size == 2 && opcode->opcode != 0xfc0000)
1209 {
1210 /* Handle bra specially. Basically treat it like jmp so
1211 that we automatically handle 8, 16 and 32 bit offsets
1212 correctly as well as jumps to an undefined address.
1213
1214 It is also important to not treat it like other bCC
1215 instructions since the long forms of bra is different
1216 from other bCC instructions. */
1217 if (opcode->opcode == 0xea00)
1218 type = 8;
1219 else
1220 type = 0;
1221 }
1222 /* jsr */
1223 else if (size == 3 && opcode->opcode == 0xfd0000)
1224 type = 6;
1225 /* jmp */
1226 else if (size == 3 && opcode->opcode == 0xfc0000)
1227 type = 8;
1228 /* bCCx */
1229 else
1230 type = 3;
1231
1232 opindex_converter.opindex = fixups[0].opindex;
1233 f = frag_var (rs_machine_dependent, 8, 8 - size, type,
1234 fixups[0].exp.X_add_symbol,
1235 fixups[0].exp.X_add_number,
1236 opindex_converter.ptr);
1237 number_to_chars_bigendian (f, insn, size);
1238 if (8 - size > 4)
1239 {
1240 number_to_chars_bigendian (f + size, 0, 4);
1241 number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
1242 }
1243 else
1244 number_to_chars_bigendian (f + size, 0, 8 - size);
1245 }
1246 else
1247 {
1248 f = frag_more (size);
1249
1250 /* Oh, what a mess. The instruction is in big endian format, but
1251 16 and 24bit immediates are little endian! */
1252 if (opcode->format == FMT_3)
1253 {
1254 number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
1255 number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
1256 }
1257 else if (opcode->format == FMT_6)
1258 {
1259 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1260 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1261 }
1262 else if (opcode->format == FMT_7)
1263 {
1264 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1265 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1266 number_to_chars_littleendian (f + 4, extension & 0xff, 1);
1267 }
1268 else
1269 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
1270
1271 /* Create any fixups. */
1272 for (i = 0; i < fc; i++)
1273 {
1274 const struct mn10200_operand *operand;
1275
1276 operand = &mn10200_operands[fixups[i].opindex];
1277 if (fixups[i].reloc != BFD_RELOC_UNUSED)
1278 {
1279 reloc_howto_type *reloc_howto;
1280 int size;
1281 int offset;
1282 fixS *fixP;
1283
1284 reloc_howto = bfd_reloc_type_lookup (stdoutput,
1285 fixups[i].reloc);
1286
1287 if (!reloc_howto)
1288 abort ();
1289
1290 size = bfd_get_reloc_size (reloc_howto);
1291
1292 if (size < 1 || size > 4)
1293 abort ();
1294
1295 offset = 4 - size;
1296 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1297 size,
1298 &fixups[i].exp,
1299 reloc_howto->pc_relative,
1300 fixups[i].reloc);
1301
1302 /* PC-relative offsets are from the first byte of the
1303 next instruction, not from the start of the current
1304 instruction. */
1305 if (reloc_howto->pc_relative)
1306 fixP->fx_offset += size;
1307 }
1308 else
1309 {
1310 int reloc, pcrel, reloc_size, offset;
1311 fixS *fixP;
1312
1313 reloc = BFD_RELOC_NONE;
1314 /* How big is the reloc? Remember SPLIT relocs are
1315 implicitly 32bits. */
1316 reloc_size = operand->bits;
1317
1318 offset = size - reloc_size / 8;
1319
1320 /* Is the reloc pc-relative? */
1321 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
1322
1323 /* Choose a proper BFD relocation type. */
1324 if (pcrel)
1325 {
1326 if (reloc_size == 8)
1327 reloc = BFD_RELOC_8_PCREL;
1328 else if (reloc_size == 24)
1329 reloc = BFD_RELOC_24_PCREL;
1330 else
1331 abort ();
1332 }
1333 else
1334 {
1335 if (reloc_size == 32)
1336 reloc = BFD_RELOC_32;
1337 else if (reloc_size == 16)
1338 reloc = BFD_RELOC_16;
1339 else if (reloc_size == 8)
1340 reloc = BFD_RELOC_8;
1341 else if (reloc_size == 24)
1342 reloc = BFD_RELOC_24;
1343 else
1344 abort ();
1345 }
1346
1347 /* Convert the size of the reloc into what fix_new_exp
1348 wants. */
1349 reloc_size = reloc_size / 8;
1350 if (reloc_size == 8)
1351 reloc_size = 0;
1352 else if (reloc_size == 16)
1353 reloc_size = 1;
1354 else if (reloc_size == 32 || reloc_size == 24)
1355 reloc_size = 2;
1356
1357 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1358 reloc_size, &fixups[i].exp, pcrel,
1359 ((bfd_reloc_code_real_type) reloc));
1360
1361 /* PC-relative offsets are from the first byte of the
1362 next instruction, not from the start of the current
1363 instruction. */
1364 if (pcrel)
1365 fixP->fx_offset += size;
1366 }
1367 }
1368 }
1369 }
1370
This page took 0.058816 seconds and 4 git commands to generate.