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