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