source: trunk/binutils/gas/config/tc-mn10200.c@ 2446

Last change on this file since 2446 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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