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