1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
2    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3    2005, 2006  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 
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 
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 
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
reg_name_search(const struct reg_name * regs,int regcount,const char * name)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
data_register_name(expressionS * expressionP)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
address_register_name(expressionS * expressionP)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
other_register_name(expressionS * expressionP)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
md_show_usage(FILE * stream)303 md_show_usage (FILE *stream)
304 {
305   fprintf (stream, _("MN10200 options:\n\
306 none yet\n"));
307 }
308 
309 int
md_parse_option(int c ATTRIBUTE_UNUSED,char * arg ATTRIBUTE_UNUSED)310 md_parse_option (int c ATTRIBUTE_UNUSED,
311 		 char *arg ATTRIBUTE_UNUSED)
312 {
313   return 0;
314 }
315 
316 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)317 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
318 {
319   return 0;
320 }
321 
322 char *
md_atof(int type,char * litp,int * sizep)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
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,fragS * fragP)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
md_section_align(asection * seg,valueT addr)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
md_begin(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
check_operand(unsigned long insn ATTRIBUTE_UNUSED,const struct mn10200_operand * operand,offsetT val)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 *
tc_gen_reloc(asection * seg ATTRIBUTE_UNUSED,fixS * fixp)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
md_estimate_size_before_relax(fragS * fragp,asection * seg)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
md_pcrel_from(fixS * fixp)844 md_pcrel_from (fixS *fixp)
845 {
846   return fixp->fx_frag->fr_address;
847 }
848 
849 void
md_apply_fix(fixS * fixP,valueT * valP ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED)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
mn10200_insert_operand(unsigned long * insnp,unsigned long * extensionp,const struct mn10200_operand * operand,offsetT val,char * file,unsigned int line,unsigned int shift)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
md_assemble(char * str)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       /* On a 64-bit host the size of an 'int' is not the same
1195 	 as the size of a pointer, so we need a union to convert
1196 	 the opindex field of the fr_cgen structure into a char *
1197 	 so that it can be stored in the frag.  We do not have
1198 	 to worry about loosing accuracy as we are not going to
1199 	 be even close to the 32bit limit of the int.  */
1200       union
1201       {
1202 	int opindex;
1203 	char * ptr;
1204       }
1205       opindex_converter;
1206       int type;
1207 
1208       /* bCC  */
1209       if (size == 2 && opcode->opcode != 0xfc0000)
1210 	{
1211 	  /* Handle bra specially.  Basically treat it like jmp so
1212 	     that we automatically handle 8, 16 and 32 bit offsets
1213 	     correctly as well as jumps to an undefined address.
1214 
1215 	     It is also important to not treat it like other bCC
1216 	     instructions since the long forms of bra is different
1217 	     from other bCC instructions.  */
1218 	  if (opcode->opcode == 0xea00)
1219 	    type = 8;
1220 	  else
1221 	    type = 0;
1222 	}
1223       /* jsr  */
1224       else if (size == 3 && opcode->opcode == 0xfd0000)
1225 	type = 6;
1226       /* jmp  */
1227       else if (size == 3 && opcode->opcode == 0xfc0000)
1228 	type = 8;
1229       /* bCCx  */
1230       else
1231 	type = 3;
1232 
1233       opindex_converter.opindex = fixups[0].opindex;
1234       f = frag_var (rs_machine_dependent, 8, 8 - size, type,
1235 		    fixups[0].exp.X_add_symbol,
1236 		    fixups[0].exp.X_add_number,
1237 		    opindex_converter.ptr);
1238       number_to_chars_bigendian (f, insn, size);
1239       if (8 - size > 4)
1240 	{
1241 	  number_to_chars_bigendian (f + size, 0, 4);
1242 	  number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
1243 	}
1244       else
1245 	number_to_chars_bigendian (f + size, 0, 8 - size);
1246     }
1247   else
1248     {
1249       f = frag_more (size);
1250 
1251       /* Oh, what a mess.  The instruction is in big endian format, but
1252 	 16 and 24bit immediates are little endian!  */
1253       if (opcode->format == FMT_3)
1254 	{
1255 	  number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
1256 	  number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
1257 	}
1258       else if (opcode->format == FMT_6)
1259 	{
1260 	  number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1261 	  number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1262 	}
1263       else if (opcode->format == FMT_7)
1264 	{
1265 	  number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1266 	  number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1267 	  number_to_chars_littleendian (f + 4, extension & 0xff, 1);
1268 	}
1269       else
1270 	number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
1271 
1272       /* Create any fixups.  */
1273       for (i = 0; i < fc; i++)
1274 	{
1275 	  const struct mn10200_operand *operand;
1276 
1277 	  operand = &mn10200_operands[fixups[i].opindex];
1278 	  if (fixups[i].reloc != BFD_RELOC_UNUSED)
1279 	    {
1280 	      reloc_howto_type *reloc_howto;
1281 	      int size;
1282 	      int offset;
1283 	      fixS *fixP;
1284 
1285 	      reloc_howto = bfd_reloc_type_lookup (stdoutput,
1286 						   fixups[i].reloc);
1287 
1288 	      if (!reloc_howto)
1289 		abort ();
1290 
1291 	      size = bfd_get_reloc_size (reloc_howto);
1292 
1293 	      if (size < 1 || size > 4)
1294 		abort ();
1295 
1296 	      offset = 4 - size;
1297 	      fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1298 				  size,
1299 				  &fixups[i].exp,
1300 				  reloc_howto->pc_relative,
1301 				  fixups[i].reloc);
1302 
1303 	      /* PC-relative offsets are from the first byte of the
1304 		 next instruction, not from the start of the current
1305 		 instruction.  */
1306 	      if (reloc_howto->pc_relative)
1307 		fixP->fx_offset += size;
1308 	    }
1309 	  else
1310 	    {
1311 	      int reloc, pcrel, reloc_size, offset;
1312 	      fixS *fixP;
1313 
1314 	      reloc = BFD_RELOC_NONE;
1315 	      /* How big is the reloc?  Remember SPLIT relocs are
1316 		 implicitly 32bits.  */
1317 	      reloc_size = operand->bits;
1318 
1319 	      offset = size - reloc_size / 8;
1320 
1321 	      /* Is the reloc pc-relative?  */
1322 	      pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
1323 
1324 	      /* Choose a proper BFD relocation type.  */
1325 	      if (pcrel)
1326 		{
1327 		  if (reloc_size == 8)
1328 		    reloc = BFD_RELOC_8_PCREL;
1329 		  else if (reloc_size == 24)
1330 		    reloc = BFD_RELOC_24_PCREL;
1331 		  else
1332 		    abort ();
1333 		}
1334 	      else
1335 		{
1336 		  if (reloc_size == 32)
1337 		    reloc = BFD_RELOC_32;
1338 		  else if (reloc_size == 16)
1339 		    reloc = BFD_RELOC_16;
1340 		  else if (reloc_size == 8)
1341 		    reloc = BFD_RELOC_8;
1342 		  else if (reloc_size == 24)
1343 		    reloc = BFD_RELOC_24;
1344 		  else
1345 		    abort ();
1346 		}
1347 
1348 	      /* Convert the size of the reloc into what fix_new_exp
1349                  wants.  */
1350 	      reloc_size = reloc_size / 8;
1351 	      if (reloc_size == 8)
1352 		reloc_size = 0;
1353 	      else if (reloc_size == 16)
1354 		reloc_size = 1;
1355 	      else if (reloc_size == 32 || reloc_size == 24)
1356 		reloc_size = 2;
1357 
1358 	      fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1359 				  reloc_size, &fixups[i].exp, pcrel,
1360 				  ((bfd_reloc_code_real_type) reloc));
1361 
1362 	      /* PC-relative offsets are from the first byte of the
1363 		 next instruction, not from the start of the current
1364 		 instruction.  */
1365 	      if (pcrel)
1366 		fixP->fx_offset += size;
1367 	    }
1368 	}
1369     }
1370 }
1371 
1372