1 /* tc-mn10300.c -- Assembler code for the Matsushita 10300
2 
3    Copyright (C) 1996 Free Software Foundation.
4 
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21 
22 #include <stdio.h>
23 #include <ctype.h>
24 #include "as.h"
25 #include "subsegs.h"
26 #include "opcode/mn10300.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 targets. */
36 
37 /* Characters which always start a comment. */
38 const char comment_chars[] = "#";
39 
40 /* Characters which start a comment at the beginning of a line.  */
41 const char line_comment_chars[] = ";#";
42 
43 /* Characters which may be used to separate multiple commands on a
44    single line.  */
45 const char line_separator_chars[] = ";";
46 
47 /* Characters which are used to indicate an exponent in a floating
48    point number.  */
49 const char EXP_CHARS[] = "eE";
50 
51 /* Characters which mean that a number is a floating point constant,
52    as in 0d1.0.  */
53 const char FLT_CHARS[] = "dD";
54 
55 
56 /* local functions */
57 static unsigned long mn10300
58   PARAMS ((unsigned long insn, const struct mn10300_operand *operand,
59 	   offsetT val, char *file, unsigned int line));
60 static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
61 static boolean register_name PARAMS ((expressionS *expressionP));
62 static boolean system_register_name PARAMS ((expressionS *expressionP));
63 static boolean cc_name PARAMS ((expressionS *expressionP));
64 
65 
66 /* fixups */
67 #define MAX_INSN_FIXUPS (5)
68 struct mn10300_fixup
69 {
70   expressionS exp;
71   int opindex;
72   bfd_reloc_code_real_type reloc;
73 };
74 struct mn10300_fixup fixups[MAX_INSN_FIXUPS];
75 static int fc;
76 
77 const char *md_shortopts = "";
78 struct option md_longopts[] = {
79   {NULL, no_argument, NULL, 0}
80 };
81 size_t md_longopts_size = sizeof(md_longopts);
82 
83 /* The target specific pseudo-ops which we support.  */
84 const pseudo_typeS md_pseudo_table[] =
85 {
86   { NULL,       NULL,           0 }
87 };
88 
89 /* Opcode hash table.  */
90 static struct hash_control *mn10300_hash;
91 
92 /* This table is sorted. Suitable for searching by a binary search. */
93 static const struct reg_name data_registers[] =
94 {
95   { "d0", 0 },
96   { "d1", 1 },
97   { "d2", 2 },
98   { "d3", 3 },
99 };
100 #define DATA_REG_NAME_CNT	(sizeof(data_registers) / sizeof(struct reg_name))
101 
102 static const struct reg_name address_registers[] =
103 {
104   { "a0", 0 },
105   { "a1", 1 },
106   { "a2", 2 },
107   { "a3", 3 },
108 };
109 #define ADDRESS_REG_NAME_CNT	(sizeof(address_registers) / sizeof(struct reg_name))
110 
111 static const struct reg_name other_registers[] =
112 {
113   { "mdr", 0 },
114   { "psw", 0 },
115   { "sp", 0 },
116 };
117 #define OTHER_REG_NAME_CNT	(sizeof(other_registers) / sizeof(struct reg_name))
118 
119 /* reg_name_search does a binary search of the given register table
120    to see if "name" is a valid regiter name.  Returns the register
121    number from the array on success, or -1 on failure. */
122 
123 static int
124 reg_name_search (regs, regcount, name)
125      const struct reg_name *regs;
126      int regcount;
127      const char *name;
128 {
129   int middle, low, high;
130   int cmp;
131 
132   low = 0;
133   high = regcount - 1;
134 
135   do
136     {
137       middle = (low + high) / 2;
138       cmp = strcasecmp (name, regs[middle].name);
139       if (cmp < 0)
140 	high = middle - 1;
141       else if (cmp > 0)
142 	low = middle + 1;
143       else
144 	  return regs[middle].value;
145     }
146   while (low <= high);
147   return -1;
148 }
149 
150 
151 /* Summary of register_name().
152  *
153  * in: Input_line_pointer points to 1st char of operand.
154  *
155  * out: A expressionS.
156  *	The operand may have been a register: in this case, X_op == O_register,
157  *	X_add_number is set to the register number, and truth is returned.
158  *	Input_line_pointer->(next non-blank) char after operand, or is in
159  *	its original state.
160  */
161 static boolean
162 data_register_name (expressionP)
163      expressionS *expressionP;
164 {
165   int reg_number;
166   char *name;
167   char *start;
168   char c;
169 
170   /* Find the spelling of the operand */
171   start = name = input_line_pointer;
172 
173   c = get_symbol_end ();
174   reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
175 
176   /* look to see if it's in the register table */
177   if (reg_number >= 0)
178     {
179       expressionP->X_op = O_register;
180       expressionP->X_add_number = reg_number;
181 
182       /* make the rest nice */
183       expressionP->X_add_symbol = NULL;
184       expressionP->X_op_symbol = NULL;
185       *input_line_pointer = c;	/* put back the delimiting char */
186       return true;
187     }
188   else
189     {
190       /* reset the line as if we had not done anything */
191       *input_line_pointer = c;   /* put back the delimiting char */
192       input_line_pointer = start; /* reset input_line pointer */
193       return false;
194     }
195 }
196 
197 /* Summary of register_name().
198  *
199  * in: Input_line_pointer points to 1st char of operand.
200  *
201  * out: A expressionS.
202  *	The operand may have been a register: in this case, X_op == O_register,
203  *	X_add_number is set to the register number, and truth is returned.
204  *	Input_line_pointer->(next non-blank) char after operand, or is in
205  *	its original state.
206  */
207 static boolean
208 address_register_name (expressionP)
209      expressionS *expressionP;
210 {
211   int reg_number;
212   char *name;
213   char *start;
214   char c;
215 
216   /* Find the spelling of the operand */
217   start = name = input_line_pointer;
218 
219   c = get_symbol_end ();
220   reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
221 
222   /* look to see if it's in the register table */
223   if (reg_number >= 0)
224     {
225       expressionP->X_op = O_register;
226       expressionP->X_add_number = reg_number;
227 
228       /* make the rest nice */
229       expressionP->X_add_symbol = NULL;
230       expressionP->X_op_symbol = NULL;
231       *input_line_pointer = c;	/* put back the delimiting char */
232       return true;
233     }
234   else
235     {
236       /* reset the line as if we had not done anything */
237       *input_line_pointer = c;   /* put back the delimiting char */
238       input_line_pointer = start; /* reset input_line pointer */
239       return false;
240     }
241 }
242 
243 /* Summary of register_name().
244  *
245  * in: Input_line_pointer points to 1st char of operand.
246  *
247  * out: A expressionS.
248  *	The operand may have been a register: in this case, X_op == O_register,
249  *	X_add_number is set to the register number, and truth is returned.
250  *	Input_line_pointer->(next non-blank) char after operand, or is in
251  *	its original state.
252  */
253 static boolean
254 other_register_name (expressionP)
255      expressionS *expressionP;
256 {
257   int reg_number;
258   char *name;
259   char *start;
260   char c;
261 
262   /* Find the spelling of the operand */
263   start = name = input_line_pointer;
264 
265   c = get_symbol_end ();
266   reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
267 
268   /* look to see if it's in the register table */
269   if (reg_number >= 0)
270     {
271       expressionP->X_op = O_register;
272       expressionP->X_add_number = reg_number;
273 
274       /* make the rest nice */
275       expressionP->X_add_symbol = NULL;
276       expressionP->X_op_symbol = NULL;
277       *input_line_pointer = c;	/* put back the delimiting char */
278       return true;
279     }
280   else
281     {
282       /* reset the line as if we had not done anything */
283       *input_line_pointer = c;   /* put back the delimiting char */
284       input_line_pointer = start; /* reset input_line pointer */
285       return false;
286     }
287 }
288 
289 void
290 md_show_usage (stream)
291   FILE *stream;
292 {
293   fprintf(stream, "MN10300 options:\n\
294 none yet\n");
295 }
296 
297 int
298 md_parse_option (c, arg)
299      int c;
300      char *arg;
301 {
302   return 0;
303 }
304 
305 symbolS *
306 md_undefined_symbol (name)
307   char *name;
308 {
309   return 0;
310 }
311 
312 char *
313 md_atof (type, litp, sizep)
314   int type;
315   char *litp;
316   int *sizep;
317 {
318   int prec;
319   LITTLENUM_TYPE words[4];
320   char *t;
321   int i;
322 
323   switch (type)
324     {
325     case 'f':
326       prec = 2;
327       break;
328 
329     case 'd':
330       prec = 4;
331       break;
332 
333     default:
334       *sizep = 0;
335       return "bad call to md_atof";
336     }
337 
338   t = atof_ieee (input_line_pointer, type, words);
339   if (t)
340     input_line_pointer = t;
341 
342   *sizep = prec * 2;
343 
344   for (i = prec - 1; i >= 0; i--)
345     {
346       md_number_to_chars (litp, (valueT) words[i], 2);
347       litp += 2;
348     }
349 
350   return NULL;
351 }
352 
353 
354 void
355 md_convert_frag (abfd, sec, fragP)
356   bfd *abfd;
357   asection *sec;
358   fragS *fragP;
359 {
360   /* printf ("call to md_convert_frag \n"); */
361   abort ();
362 }
363 
364 valueT
365 md_section_align (seg, addr)
366      asection *seg;
367      valueT addr;
368 {
369   int align = bfd_get_section_alignment (stdoutput, seg);
370   return ((addr + (1 << align) - 1) & (-1 << align));
371 }
372 
373 void
374 md_begin ()
375 {
376   char *prev_name = "";
377   register const struct mn10300_opcode *op;
378 
379   mn10300_hash = hash_new();
380 
381   /* Insert unique names into hash table.  The MN10300 instruction set
382      has many identical opcode names that have different opcodes based
383      on the operands.  This hash table then provides a quick index to
384      the first opcode with a particular name in the opcode table.  */
385 
386   op     = mn10300_opcodes;
387   while (op->name)
388     {
389       if (strcmp (prev_name, op->name))
390 	{
391 	  prev_name = (char *) op->name;
392 	  hash_insert (mn10300_hash, op->name, (char *) op);
393 	}
394       op++;
395     }
396 }
397 
398 void
399 md_assemble (str)
400      char *str;
401 {
402   char *s;
403   struct mn10300_opcode *opcode;
404   struct mn10300_opcode *next_opcode;
405   const unsigned char *opindex_ptr;
406   int next_opindex;
407   unsigned long insn, extension, size;
408   char *f;
409   int i;
410   int match;
411   bfd_reloc_code_real_type reloc;
412 
413   /* Get the opcode.  */
414   for (s = str; *s != '\0' && ! isspace (*s); s++)
415     ;
416   if (*s != '\0')
417     *s++ = '\0';
418 
419   /* find the first opcode with the proper name */
420   opcode = (struct mn10300_opcode *)hash_find (mn10300_hash, str);
421   if (opcode == NULL)
422     {
423       as_bad ("Unrecognized opcode: `%s'", str);
424       return;
425     }
426 
427   str = s;
428   while (isspace (*str))
429     ++str;
430 
431   input_line_pointer = str;
432 
433   for(;;)
434     {
435       const char *errmsg = NULL;
436       int op_idx;
437       char *hold;
438       int extra_shift = 0;
439 
440       fc = 0;
441       match = 0;
442       next_opindex = 0;
443       insn = opcode->opcode;
444       extension = 0;
445       for (op_idx = 1, opindex_ptr = opcode->operands;
446 	   *opindex_ptr != 0;
447 	   opindex_ptr++, op_idx++)
448 	{
449 	  const struct mn10300_operand *operand;
450 	  expressionS ex;
451 
452 	  if (next_opindex == 0)
453 	    {
454 	      operand = &mn10300_operands[*opindex_ptr];
455 	    }
456 	  else
457 	    {
458 	      operand = &mn10300_operands[next_opindex];
459 	      next_opindex = 0;
460 	    }
461 
462 	  errmsg = NULL;
463 
464 	  while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
465 	    ++str;
466 
467 	  /* Gather the operand. */
468 	  hold = input_line_pointer;
469 	  input_line_pointer = str;
470 
471 	  if (operand->flags & MN10300_OPERAND_PAREN)
472 	    {
473 	      if (*input_line_pointer != ')' && *input_line_pointer != '(')
474 		{
475 		  input_line_pointer = hold;
476 		  str = hold;
477 		  goto error;
478 		}
479 	      input_line_pointer++;
480 	      goto keep_going;
481 	    }
482 	  /* See if we can match the operands.  */
483 	  else if (operand->flags & MN10300_OPERAND_DREG)
484 	    {
485 	      if (!data_register_name (&ex))
486 		{
487 		  input_line_pointer = hold;
488 		  str = hold;
489 		  goto error;
490 		}
491 	    }
492 	  else if (operand->flags & MN10300_OPERAND_AREG)
493 	    {
494 	      if (!address_register_name (&ex))
495 		{
496 		  input_line_pointer = hold;
497 		  str = hold;
498 		  goto error;
499 		}
500 	    }
501 	  else if (operand->flags & MN10300_OPERAND_SP)
502 	    {
503 	      char *start = input_line_pointer;
504 	      char c = get_symbol_end ();
505 
506 	      if (strcmp (start, "sp") != 0)
507 		{
508 		  *input_line_pointer = c;
509 		  input_line_pointer = hold;
510 		  str = hold;
511 		  goto error;
512 		}
513 	      *input_line_pointer = c;
514 	      goto keep_going;
515 	    }
516 	  else if (operand->flags & MN10300_OPERAND_PSW)
517 	    {
518 	      char *start = input_line_pointer;
519 	      char c = get_symbol_end ();
520 
521 	      if (strcmp (start, "psw") != 0)
522 		{
523 		  *input_line_pointer = c;
524 		  input_line_pointer = hold;
525 		  str = hold;
526 		  goto error;
527 		}
528 	      *input_line_pointer = c;
529 	      goto keep_going;
530 	    }
531 	  else if (operand->flags & MN10300_OPERAND_MDR)
532 	    {
533 	      char *start = input_line_pointer;
534 	      char c = get_symbol_end ();
535 
536 	      if (strcmp (start, "mdr") != 0)
537 		{
538 		  *input_line_pointer = c;
539 		  input_line_pointer = hold;
540 		  str = hold;
541 		  goto error;
542 		}
543 	      *input_line_pointer = c;
544 	      goto keep_going;
545 	    }
546 	  else if (data_register_name (&ex))
547 	    {
548 	      input_line_pointer = hold;
549 	      str = hold;
550 	      goto error;
551 	    }
552 	  else if (address_register_name (&ex))
553 	    {
554 	      input_line_pointer = hold;
555 	      str = hold;
556 	      goto error;
557 	    }
558 	  else if (other_register_name (&ex))
559 	    {
560 	      input_line_pointer = hold;
561 	      str = hold;
562 	      goto error;
563 	    }
564 	  else if (*str == ')' || *str == '(')
565 	    {
566 	      input_line_pointer = hold;
567 	      str = hold;
568 	      goto error;
569 	    }
570 	  else
571 	    {
572 	      expression (&ex);
573 	    }
574 
575 	  switch (ex.X_op)
576 	    {
577 	    case O_illegal:
578 	      errmsg = "illegal operand";
579 	      goto error;
580 	    case O_absent:
581 	      errmsg = "missing operand";
582 	      goto error;
583 	    case O_register:
584 	      if (operand->flags & (MN10300_OPERAND_DREG
585 				    | MN10300_OPERAND_AREG) == 0)
586 		{
587 		  input_line_pointer = hold;
588 		  str = hold;
589 		  goto error;
590 		}
591 
592 	      if (opcode->format == FMT_D1 || opcode->format == FMT_S1)
593 		extra_shift = 8;
594 	      else if (opcode->format == FMT_D2 || opcode->format == FMT_D4
595 		       || opcode->format == FMT_S2 || opcode->format == FMT_S4
596 		       || opcode->format == FMT_S6 || opcode->format == FMT_D5)
597 		extra_shift = 16;
598 	      else
599 		extra_shift = 0;
600 
601 	      mn10300_insert_operand (&insn, &extension, operand,
602 				      ex.X_add_number, (char *) NULL,
603 				      0, extra_shift);
604 
605 	      break;
606 
607 	    case O_constant:
608 	      /* If this operand can be promoted, and it doesn't
609 		 fit into the allocated bitfield for this insn,
610 		 then promote it (ie this opcode does not match).  */
611 	      if (operand->flags & MN10300_OPERAND_PROMOTE
612 		  && ! check_operand (insn, operand, ex.X_add_number))
613 		{
614 		  input_line_pointer = hold;
615 		  str = hold;
616 		  goto error;
617 		}
618 
619 	      mn10300_insert_operand (&insn, &extension, operand,
620 				      ex.X_add_number, (char *) NULL,
621 				      0, 0);
622 	      break;
623 
624 	    default:
625 	      /* If this operand can be promoted, then this opcode didn't
626 		 match since we can't know if it needed promotion!  */
627 	      if (operand->flags & MN10300_OPERAND_PROMOTE)
628 		{
629 		  input_line_pointer = hold;
630 		  str = hold;
631 		  goto error;
632 		}
633 
634 	      /* We need to generate a fixup for this expression.  */
635 	      if (fc >= MAX_INSN_FIXUPS)
636 		as_fatal ("too many fixups");
637 	      fixups[fc].exp = ex;
638 	      fixups[fc].opindex = *opindex_ptr;
639 	      fixups[fc].reloc = BFD_RELOC_UNUSED;
640 	      ++fc;
641 	      break;
642 	    }
643 
644 keep_going:
645 	  str = input_line_pointer;
646 	  input_line_pointer = hold;
647 
648 	  while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
649 	    ++str;
650 
651 	}
652 
653       /* Make sure we used all the operands!  */
654       if (*str != ',')
655 	match = 1;
656 
657     error:
658       if (match == 0)
659         {
660 	  next_opcode = opcode + 1;
661 	  if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
662 	    {
663 	      opcode = next_opcode;
664 	      continue;
665 	    }
666 
667 	  as_bad ("%s", errmsg);
668 	  return;
669         }
670       break;
671     }
672 
673   while (isspace (*str))
674     ++str;
675 
676   if (*str != '\0')
677     as_bad ("junk at end of line: `%s'", str);
678 
679   input_line_pointer = str;
680 
681   /* Determine the size of the instruction.  */
682   if (opcode->format == FMT_S0)
683     size = 1;
684 
685   if (opcode->format == FMT_S1 || opcode->format == FMT_D0)
686     size = 2;
687 
688   if (opcode->format == FMT_S2 || opcode->format == FMT_D1)
689     size = 3;
690 
691   if (opcode->format == FMT_S4)
692     size = 5;
693 
694   if (opcode->format == FMT_S6 || opcode->format == FMT_D5)
695     size = 7;
696 
697   if (opcode->format == FMT_D2)
698     size = 4;
699 
700   if (opcode->format == FMT_D4)
701     size = 6;
702 
703   /* Write out the instruction.  */
704 
705   f = frag_more (size);
706   number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
707   if (size > 4)
708     number_to_chars_bigendian (f + 4, extension, size - 4);
709 }
710 
711 
712 /* if while processing a fixup, a reloc really needs to be created */
713 /* then it is done here */
714 
715 arelent *
716 tc_gen_reloc (seg, fixp)
717      asection *seg;
718      fixS *fixp;
719 {
720   arelent *reloc;
721   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
722   reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
723   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
724   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
725   if (reloc->howto == (reloc_howto_type *) NULL)
726     {
727       as_bad_where (fixp->fx_file, fixp->fx_line,
728                     "reloc %d not supported by object file format", (int)fixp->fx_r_type);
729       return NULL;
730     }
731   reloc->addend = fixp->fx_addnumber;
732   /*  printf("tc_gen_reloc: addr=%x  addend=%x\n", reloc->address, reloc->addend); */
733   return reloc;
734 }
735 
736 int
737 md_estimate_size_before_relax (fragp, seg)
738      fragS *fragp;
739      asection *seg;
740 {
741   return 0;
742 }
743 
744 long
745 md_pcrel_from (fixp)
746      fixS *fixp;
747 {
748   if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
749     {
750       /* The symbol is undefined.  Let the linker figure it out.  */
751       return 0;
752     }
753   return fixp->fx_frag->fr_address + fixp->fx_where;
754 }
755 
756 int
757 md_apply_fix3 (fixp, valuep, seg)
758      fixS *fixp;
759      valueT *valuep;
760      segT seg;
761 {
762   valueT value;
763   char *where;
764 
765   fixp->fx_done = 1;
766   return 0;
767 
768   if (fixp->fx_addsy == (symbolS *) NULL)
769     {
770       value = *valuep;
771       fixp->fx_done = 1;
772     }
773   else if (fixp->fx_pcrel)
774     value = *valuep;
775   else
776     {
777       value = fixp->fx_offset;
778       if (fixp->fx_subsy != (symbolS *) NULL)
779 	{
780 	  if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
781 	    value -= S_GET_VALUE (fixp->fx_subsy);
782 	  else
783 	    {
784 	      /* We don't actually support subtracting a symbol.  */
785 	      as_bad_where (fixp->fx_file, fixp->fx_line,
786 			    "expression too complex");
787 	    }
788 	}
789     }
790 
791   /* printf("md_apply_fix: value=0x%x  type=%d\n",  value, fixp->fx_r_type); */
792 
793   if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
794     {
795       int opindex;
796       const struct mn10300_operand *operand;
797       char *where;
798       unsigned long insn, extension;
799 
800       opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
801       operand = &mn10300_operands[opindex];
802 
803       /* Fetch the instruction, insert the fully resolved operand
804          value, and stuff the instruction back again.
805 
806 	 Note the instruction has been stored in little endian
807 	 format!  */
808       where = fixp->fx_frag->fr_literal + fixp->fx_where;
809 
810       insn = bfd_getl32((unsigned char *) where);
811       extension = 0;
812       mn10300_insert_operand (&insn, &extension, operand,
813 			      (offsetT) value, fixp->fx_file,
814 			      fixp->fx_line, 0);
815       bfd_putl32((bfd_vma) insn, (unsigned char *) where);
816 
817       if (fixp->fx_done)
818 	{
819 	  /* Nothing else to do here. */
820 	  return 1;
821 	}
822 
823       /* Determine a BFD reloc value based on the operand information.
824 	 We are only prepared to turn a few of the operands into relocs. */
825 
826 	{
827 	  as_bad_where(fixp->fx_file, fixp->fx_line,
828 		       "unresolved expression that must be resolved");
829 	  fixp->fx_done = 1;
830 	  return 1;
831 	}
832     }
833   else if (fixp->fx_done)
834     {
835       /* We still have to insert the value into memory!  */
836       where = fixp->fx_frag->fr_literal + fixp->fx_where;
837       if (fixp->fx_size == 1)
838 	*where = value & 0xff;
839       if (fixp->fx_size == 2)
840 	bfd_putl16(value & 0xffff, (unsigned char *) where);
841       if (fixp->fx_size == 4)
842 	bfd_putl32(value, (unsigned char *) where);
843     }
844 
845   fixp->fx_addnumber = value;
846   return 1;
847 }
848 
849 /* Insert an operand value into an instruction.  */
850 
851 static void
852 mn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift)
853      unsigned long *insnp;
854      unsigned long *extensionp;
855      const struct mn10300_operand *operand;
856      offsetT val;
857      char *file;
858      unsigned int line;
859      unsigned int shift;
860 {
861   /* No need to check 32bit operands for a bit.  Note that
862      MN10300_OPERAND_SPLIT is an implicit 32bit operand.  */
863   if (operand->bits != 32
864       && (operand->flags & MN10300_OPERAND_SPLIT) == 0)
865     {
866       long min, max;
867       offsetT test;
868 
869       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
870 	{
871 	  max = (1 << (operand->bits - 1)) - 1;
872 	  min = - (1 << (operand->bits - 1));
873 	}
874       else
875         {
876           max = (1 << operand->bits) - 1;
877           min = 0;
878         }
879 
880       test = val;
881 
882 
883       if (test < (offsetT) min || test > (offsetT) max)
884         {
885           const char *err =
886             "operand out of range (%s not between %ld and %ld)";
887           char buf[100];
888 
889           sprint_value (buf, test);
890           if (file == (char *) NULL)
891             as_warn (err, buf, min, max);
892           else
893             as_warn_where (file, line, err, buf, min, max);
894         }
895     }
896 
897   if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
898     {
899       *insnp |= (val >> 32 - operand->bits) & ((1 << operand->bits) - 1);
900       *extensionp |= ((val & ((1 << (32 - operand->bits)) - 1))
901 		      << operand->shift);
902     }
903   else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0)
904     {
905       *insnp |= (((long) val & ((1 << operand->bits) - 1))
906 		 << (operand->shift + shift));
907 
908       if ((operand->flags & MN10300_OPERAND_REPEATED) != 0)
909 	*insnp |= (((long) val & ((1 << operand->bits) - 1))
910 		   << (operand->shift + shift + 2));
911     }
912   else
913     {
914       *extensionp |= (((long) val & ((1 << operand->bits) - 1))
915 		      << (operand->shift + shift));
916 
917       if ((operand->flags & MN10300_OPERAND_REPEATED) != 0)
918 	*extensionp |= (((long) val & ((1 << operand->bits) - 1))
919 			<< (operand->shift + shift + 2));
920     }
921 }
922 
923 static unsigned long
924 check_operand (insn, operand, val)
925      unsigned long insn;
926      const struct mn10300_operand *operand;
927      offsetT val;
928 {
929   /* No need to check 32bit operands for a bit.  Note that
930      MN10300_OPERAND_SPLIT is an implicit 32bit operand.  */
931   if (operand->bits != 32
932       && (operand->flags & MN10300_OPERAND_SPLIT) == 0)
933     {
934       long min, max;
935       offsetT test;
936 
937       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
938 	{
939 	  max = (1 << (operand->bits - 1)) - 1;
940 	  min = - (1 << (operand->bits - 1));
941 	}
942       else
943         {
944           max = (1 << operand->bits) - 1;
945           min = 0;
946         }
947 
948       test = val;
949 
950 
951       if (test < (offsetT) min || test > (offsetT) max)
952 	return 0;
953       else
954 	return 1;
955     }
956   return 1;
957 }
958