]> Git Repo - binutils.git/blob - gas/config/tc-mn10300.c
* config/tc-mn10300.c (md_assemble): Use FMT_* macros for
[binutils.git] / gas / config / tc-mn10300.c
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 \f
28 /* Structure to hold information about predefined registers.  */
29 struct reg_name
30 {
31   const char *name;
32   int value;
33 };
34
35 /* Generic assembler global variables which must be defined by all 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 \f
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 \f
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, 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
439       fc = 0;
440       match = 0;
441       next_opindex = 0;
442       insn = opcode->opcode;
443       for (op_idx = 1, opindex_ptr = opcode->operands;
444            *opindex_ptr != 0;
445            opindex_ptr++, op_idx++)
446         {
447           const struct mn10300_operand *operand;
448           expressionS ex;
449
450           if (next_opindex == 0)
451             {
452               operand = &mn10300_operands[*opindex_ptr];
453             }
454           else
455             {
456               operand = &mn10300_operands[next_opindex];
457               next_opindex = 0;
458             }
459
460           errmsg = NULL;
461
462           while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
463             ++str;
464
465           /* Gather the operand. */
466           hold = input_line_pointer;
467           input_line_pointer = str;
468
469           if (operand->flags & MN10300_OPERAND_PAREN)
470             {
471               if (*input_line_pointer != ')' && *input_line_pointer != '(')
472                 {
473                   input_line_pointer = hold;
474                   str = hold;
475                   goto error;
476                 }
477               input_line_pointer++;
478               goto keep_going;
479             }
480           /* See if we can match the operands.  */
481           else if (operand->flags & MN10300_OPERAND_DREG)
482             {
483               if (!data_register_name (&ex))
484                 {
485                   input_line_pointer = hold;
486                   str = hold;
487                   goto error;
488                 }
489             }
490           else if (operand->flags & MN10300_OPERAND_AREG)
491             {
492               if (!address_register_name (&ex))
493                 {
494                   input_line_pointer = hold;
495                   str = hold;
496                   goto error;
497                 }
498             }
499           else if (operand->flags & MN10300_OPERAND_SP)
500             {
501               char *start = input_line_pointer;
502               char c = get_symbol_end ();
503
504               if (strcmp (start, "sp") != 0)
505                 {
506                   *input_line_pointer = c;
507                   input_line_pointer = hold;
508                   str = hold;
509                   goto error;
510                 }
511               *input_line_pointer = c;
512               goto keep_going;
513             }
514           else if (operand->flags & MN10300_OPERAND_PSW)
515             {
516               char *start = input_line_pointer;
517               char c = get_symbol_end ();
518
519               if (strcmp (start, "psw") != 0)
520                 {
521                   *input_line_pointer = c;
522                   input_line_pointer = hold;
523                   str = hold;
524                   goto error;
525                 }
526               *input_line_pointer = c;
527               goto keep_going;
528             }
529           else if (operand->flags & MN10300_OPERAND_MDR)
530             {
531               char *start = input_line_pointer;
532               char c = get_symbol_end ();
533
534               if (strcmp (start, "mdr") != 0)
535                 {
536                   *input_line_pointer = c;
537                   input_line_pointer = hold;
538                   str = hold;
539                   goto error;
540                 }
541               *input_line_pointer = c;
542               goto keep_going;
543             }
544           else if (data_register_name (&ex))
545             {
546               input_line_pointer = hold;
547               str = hold;
548               goto error;
549             }
550           else if (address_register_name (&ex))
551             {
552               input_line_pointer = hold;
553               str = hold;
554               goto error;
555             }
556           else if (other_register_name (&ex))
557             {
558               input_line_pointer = hold;
559               str = hold;
560               goto error;
561             }
562           else if (*str == ')' || *str == '(')
563             {
564               input_line_pointer = hold;
565               str = hold;
566               goto error;
567             }
568           else
569             {
570               expression (&ex);
571             }
572
573           switch (ex.X_op) 
574             {
575             case O_illegal:
576               errmsg = "illegal operand";
577               goto error;
578             case O_absent:
579               errmsg = "missing operand";
580               goto error;
581             case O_register:
582               if (operand->flags & (MN10300_OPERAND_DREG 
583                                     | MN10300_OPERAND_AREG) == 0)
584                 {
585                   input_line_pointer = hold;
586                   str = hold;
587                   goto error;
588                 }
589                 
590               insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
591                                           (char *) NULL, 0);
592               break;
593
594             case O_constant:
595               /* If this operand can be promoted, and it doesn't
596                  fit into the allocated bitfield for this insn,
597                  then promote it (ie this opcode does not match).  */
598               if (operand->flags & MN10300_OPERAND_PROMOTE
599                   && ! check_operand (insn, operand, ex.X_add_number))
600                 {
601                   input_line_pointer = hold;
602                   str = hold;
603                   goto error;
604                 }
605
606               insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
607                                           (char *) NULL, 0);
608               break;
609
610             default:
611               /* If this operand can be promoted, then this opcode didn't
612                  match since we can't know if it needed promotion!  */
613               if (operand->flags & MN10300_OPERAND_PROMOTE)
614                 {
615                   input_line_pointer = hold;
616                   str = hold;
617                   goto error;
618                 }
619
620               /* We need to generate a fixup for this expression.  */
621               if (fc >= MAX_INSN_FIXUPS)
622                 as_fatal ("too many fixups");
623               fixups[fc].exp = ex;
624               fixups[fc].opindex = *opindex_ptr;
625               fixups[fc].reloc = BFD_RELOC_UNUSED;
626               ++fc;
627               break;
628             }
629
630 keep_going:
631           str = input_line_pointer;
632           input_line_pointer = hold;
633
634           while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
635             ++str;
636
637         }
638
639       /* Make sure we used all the operands!  */
640       if (*str != ',')
641         match = 1;
642
643     error:
644       if (match == 0)
645         {
646           next_opcode = opcode + 1;
647           if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
648             {
649               opcode = next_opcode;
650               continue;
651             }
652           
653           as_bad ("%s", errmsg);
654           return;
655         }
656       break;
657     }
658       
659   while (isspace (*str))
660     ++str;
661
662   if (*str != '\0')
663     as_bad ("junk at end of line: `%s'", str);
664
665   input_line_pointer = str;
666
667   /* Determine the size of the instruction.  */
668   if (opcode->format == FMT_S0)
669     size = 1;
670
671   if (opcode->format == FMT_S1 || opcode->format == FMT_D0)
672     size = 2;
673
674   if (opcode->format == FMT_S2 || opcode->format == FMT_D1)
675     size = 3;
676
677   if (opcode->format == FMT_S4)
678     size = 5;
679
680   if (opcode->format == FMT_S6 || opcode->format == FMT_D5)
681     size = 7;
682
683   if (opcode->format == FMT_D2)
684     size = 4;
685
686   if (opcode->format == FMT_D4)
687     size = 6;
688
689   /* Write out the instruction.  */
690
691   f = frag_more (size);
692   number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
693   if (size > 4)
694     number_to_chars_bigendian (f + 4, 0, size - 4);
695 }
696
697
698 /* if while processing a fixup, a reloc really needs to be created */
699 /* then it is done here */
700                  
701 arelent *
702 tc_gen_reloc (seg, fixp)
703      asection *seg;
704      fixS *fixp;
705 {
706   arelent *reloc;
707   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
708   reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
709   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
710   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
711   if (reloc->howto == (reloc_howto_type *) NULL)
712     {
713       as_bad_where (fixp->fx_file, fixp->fx_line,
714                     "reloc %d not supported by object file format", (int)fixp->fx_r_type);
715       return NULL;
716     }
717   reloc->addend = fixp->fx_addnumber;
718   /*  printf("tc_gen_reloc: addr=%x  addend=%x\n", reloc->address, reloc->addend); */
719   return reloc;
720 }
721
722 int
723 md_estimate_size_before_relax (fragp, seg)
724      fragS *fragp;
725      asection *seg;
726 {
727   return 0;
728
729
730 long
731 md_pcrel_from (fixp)
732      fixS *fixp;
733 {
734   if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
735     {
736       /* The symbol is undefined.  Let the linker figure it out.  */
737       return 0;
738     }
739   return fixp->fx_frag->fr_address + fixp->fx_where;
740 }
741
742 int
743 md_apply_fix3 (fixp, valuep, seg)
744      fixS *fixp;
745      valueT *valuep;
746      segT seg;
747 {
748   valueT value;
749   char *where;
750
751   fixp->fx_done = 1;
752   return 0;
753
754   if (fixp->fx_addsy == (symbolS *) NULL)
755     {
756       value = *valuep;
757       fixp->fx_done = 1;
758     }
759   else if (fixp->fx_pcrel)
760     value = *valuep;
761   else
762     {
763       value = fixp->fx_offset;
764       if (fixp->fx_subsy != (symbolS *) NULL)
765         {
766           if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
767             value -= S_GET_VALUE (fixp->fx_subsy);
768           else
769             {
770               /* We don't actually support subtracting a symbol.  */
771               as_bad_where (fixp->fx_file, fixp->fx_line,
772                             "expression too complex");
773             }
774         }
775     }
776
777   /* printf("md_apply_fix: value=0x%x  type=%d\n",  value, fixp->fx_r_type); */
778
779   if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
780     {
781       int opindex;
782       const struct mn10300_operand *operand;
783       char *where;
784       unsigned long insn;
785
786       opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
787       operand = &mn10300_operands[opindex];
788
789       /* Fetch the instruction, insert the fully resolved operand
790          value, and stuff the instruction back again.
791
792          Note the instruction has been stored in little endian
793          format!  */
794       where = fixp->fx_frag->fr_literal + fixp->fx_where;
795
796       insn = bfd_getl32((unsigned char *) where);
797       insn = mn10300_insert_operand (insn, operand, (offsetT) value,
798                                   fixp->fx_file, fixp->fx_line);
799       bfd_putl32((bfd_vma) insn, (unsigned char *) where);
800
801       if (fixp->fx_done)
802         {
803           /* Nothing else to do here. */
804           return 1;
805         }
806
807       /* Determine a BFD reloc value based on the operand information.  
808          We are only prepared to turn a few of the operands into relocs. */
809
810         {
811           as_bad_where(fixp->fx_file, fixp->fx_line,
812                        "unresolved expression that must be resolved");
813           fixp->fx_done = 1;
814           return 1;
815         }
816     }
817   else if (fixp->fx_done)
818     {
819       /* We still have to insert the value into memory!  */
820       where = fixp->fx_frag->fr_literal + fixp->fx_where;
821       if (fixp->fx_size == 1)
822         *where = value & 0xff;
823       if (fixp->fx_size == 2)
824         bfd_putl16(value & 0xffff, (unsigned char *) where);
825       if (fixp->fx_size == 4)
826         bfd_putl32(value, (unsigned char *) where);
827     }
828
829   fixp->fx_addnumber = value;
830   return 1;
831 }
832
833 /* Insert an operand value into an instruction.  */
834
835 static unsigned long
836 mn10300_insert_operand (insn, operand, val, file, line)
837      unsigned long insn;
838      const struct mn10300_operand *operand;
839      offsetT val;
840      char *file;
841      unsigned int line;
842 {
843   if (operand->bits != 32)
844     {
845       long min, max;
846       offsetT test;
847
848       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
849         {
850           max = (1 << (operand->bits - 1)) - 1;
851           min = - (1 << (operand->bits - 1));
852         }
853       else
854         {
855           max = (1 << operand->bits) - 1;
856           min = 0;
857         }
858
859       test = val;
860
861
862       if (test < (offsetT) min || test > (offsetT) max)
863         {
864           const char *err =
865             "operand out of range (%s not between %ld and %ld)";
866           char buf[100];
867
868           sprint_value (buf, test);
869           if (file == (char *) NULL)
870             as_warn (err, buf, min, max);
871           else
872             as_warn_where (file, line, err, buf, min, max);
873         }
874     }
875
876   insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
877   return insn;
878 }
879
880 static unsigned long
881 check_operand (insn, operand, val)
882      unsigned long insn;
883      const struct mn10300_operand *operand;
884      offsetT val;
885 {
886   if (operand->bits != 32)
887     {
888       long min, max;
889       offsetT test;
890
891       if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
892         {
893           max = (1 << (operand->bits - 1)) - 1;
894           min = - (1 << (operand->bits - 1));
895         }
896       else
897         {
898           max = (1 << operand->bits) - 1;
899           min = 0;
900         }
901
902       test = val;
903
904
905       if (test < (offsetT) min || test > (offsetT) max)
906         return 0;
907       else
908         return 1;
909     }
910   return 1;
911 }
This page took 0.075178 seconds and 4 git commands to generate.