]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-mn10200.c
* config/tc-hppa.c (struct hppa_fix_struct): Steak fx_r_field's type
[thirdparty/binutils-gdb.git] / gas / config / tc-mn10200.c
1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
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/mn10200.h"
27 \f
28 /* Structure to hold information about predefined registers. */
29 struct reg_name
30 {
31 const char *name;
32 int value;
33 };
34
35 /* Generic assembler global variables which must be defined by all 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 void mn10200_insert_operand PARAMS ((unsigned long *, unsigned long *,
58 const struct mn10200_operand *,
59 offsetT, char *, unsigned,
60 unsigned));
61 static unsigned long check_operand PARAMS ((unsigned long,
62 const struct mn10200_operand *,
63 offsetT));
64 static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
65 static boolean data_register_name PARAMS ((expressionS *expressionP));
66 static boolean address_register_name PARAMS ((expressionS *expressionP));
67 static boolean other_register_name PARAMS ((expressionS *expressionP));
68
69
70 /* fixups */
71 #define MAX_INSN_FIXUPS (5)
72 struct mn10200_fixup
73 {
74 expressionS exp;
75 int opindex;
76 bfd_reloc_code_real_type reloc;
77 };
78 struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
79 static int fc;
80 \f
81 const char *md_shortopts = "";
82 struct option md_longopts[] = {
83 {NULL, no_argument, NULL, 0}
84 };
85 size_t md_longopts_size = sizeof(md_longopts);
86
87 /* The target specific pseudo-ops which we support. */
88 const pseudo_typeS md_pseudo_table[] =
89 {
90 { NULL, NULL, 0 }
91 };
92
93 /* Opcode hash table. */
94 static struct hash_control *mn10200_hash;
95
96 /* This table is sorted. Suitable for searching by a binary search. */
97 static const struct reg_name data_registers[] =
98 {
99 { "d0", 0 },
100 { "d1", 1 },
101 { "d2", 2 },
102 { "d3", 3 },
103 };
104 #define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name))
105
106 static const struct reg_name address_registers[] =
107 {
108 { "a0", 0 },
109 { "a1", 1 },
110 { "a2", 2 },
111 { "a3", 3 },
112 };
113 #define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name))
114
115 static const struct reg_name other_registers[] =
116 {
117 { "mdr", 0 },
118 { "psw", 0 },
119 };
120 #define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name))
121
122 /* reg_name_search does a binary search of the given register table
123 to see if "name" is a valid regiter name. Returns the register
124 number from the array on success, or -1 on failure. */
125
126 static int
127 reg_name_search (regs, regcount, name)
128 const struct reg_name *regs;
129 int regcount;
130 const char *name;
131 {
132 int middle, low, high;
133 int cmp;
134
135 low = 0;
136 high = regcount - 1;
137
138 do
139 {
140 middle = (low + high) / 2;
141 cmp = strcasecmp (name, regs[middle].name);
142 if (cmp < 0)
143 high = middle - 1;
144 else if (cmp > 0)
145 low = middle + 1;
146 else
147 return regs[middle].value;
148 }
149 while (low <= high);
150 return -1;
151 }
152
153
154 /* Summary of register_name().
155 *
156 * in: Input_line_pointer points to 1st char of operand.
157 *
158 * out: A expressionS.
159 * The operand may have been a register: in this case, X_op == O_register,
160 * X_add_number is set to the register number, and truth is returned.
161 * Input_line_pointer->(next non-blank) char after operand, or is in
162 * its original state.
163 */
164 static boolean
165 data_register_name (expressionP)
166 expressionS *expressionP;
167 {
168 int reg_number;
169 char *name;
170 char *start;
171 char c;
172
173 /* Find the spelling of the operand */
174 start = name = input_line_pointer;
175
176 c = get_symbol_end ();
177 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
178
179 /* look to see if it's in the register table */
180 if (reg_number >= 0)
181 {
182 expressionP->X_op = O_register;
183 expressionP->X_add_number = reg_number;
184
185 /* make the rest nice */
186 expressionP->X_add_symbol = NULL;
187 expressionP->X_op_symbol = NULL;
188 *input_line_pointer = c; /* put back the delimiting char */
189 return true;
190 }
191 else
192 {
193 /* reset the line as if we had not done anything */
194 *input_line_pointer = c; /* put back the delimiting char */
195 input_line_pointer = start; /* reset input_line pointer */
196 return false;
197 }
198 }
199
200 /* Summary of register_name().
201 *
202 * in: Input_line_pointer points to 1st char of operand.
203 *
204 * out: A expressionS.
205 * The operand may have been a register: in this case, X_op == O_register,
206 * X_add_number is set to the register number, and truth is returned.
207 * Input_line_pointer->(next non-blank) char after operand, or is in
208 * its original state.
209 */
210 static boolean
211 address_register_name (expressionP)
212 expressionS *expressionP;
213 {
214 int reg_number;
215 char *name;
216 char *start;
217 char c;
218
219 /* Find the spelling of the operand */
220 start = name = input_line_pointer;
221
222 c = get_symbol_end ();
223 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
224
225 /* look to see if it's in the register table */
226 if (reg_number >= 0)
227 {
228 expressionP->X_op = O_register;
229 expressionP->X_add_number = reg_number;
230
231 /* make the rest nice */
232 expressionP->X_add_symbol = NULL;
233 expressionP->X_op_symbol = NULL;
234 *input_line_pointer = c; /* put back the delimiting char */
235 return true;
236 }
237 else
238 {
239 /* reset the line as if we had not done anything */
240 *input_line_pointer = c; /* put back the delimiting char */
241 input_line_pointer = start; /* reset input_line pointer */
242 return false;
243 }
244 }
245
246 /* Summary of register_name().
247 *
248 * in: Input_line_pointer points to 1st char of operand.
249 *
250 * out: A expressionS.
251 * The operand may have been a register: in this case, X_op == O_register,
252 * X_add_number is set to the register number, and truth is returned.
253 * Input_line_pointer->(next non-blank) char after operand, or is in
254 * its original state.
255 */
256 static boolean
257 other_register_name (expressionP)
258 expressionS *expressionP;
259 {
260 int reg_number;
261 char *name;
262 char *start;
263 char c;
264
265 /* Find the spelling of the operand */
266 start = name = input_line_pointer;
267
268 c = get_symbol_end ();
269 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
270
271 /* look to see if it's in the register table */
272 if (reg_number >= 0)
273 {
274 expressionP->X_op = O_register;
275 expressionP->X_add_number = reg_number;
276
277 /* make the rest nice */
278 expressionP->X_add_symbol = NULL;
279 expressionP->X_op_symbol = NULL;
280 *input_line_pointer = c; /* put back the delimiting char */
281 return true;
282 }
283 else
284 {
285 /* reset the line as if we had not done anything */
286 *input_line_pointer = c; /* put back the delimiting char */
287 input_line_pointer = start; /* reset input_line pointer */
288 return false;
289 }
290 }
291
292 void
293 md_show_usage (stream)
294 FILE *stream;
295 {
296 fprintf(stream, "MN10200 options:\n\
297 none yet\n");
298 }
299
300 int
301 md_parse_option (c, arg)
302 int c;
303 char *arg;
304 {
305 return 0;
306 }
307
308 symbolS *
309 md_undefined_symbol (name)
310 char *name;
311 {
312 return 0;
313 }
314
315 char *
316 md_atof (type, litp, sizep)
317 int type;
318 char *litp;
319 int *sizep;
320 {
321 int prec;
322 LITTLENUM_TYPE words[4];
323 char *t;
324 int i;
325
326 switch (type)
327 {
328 case 'f':
329 prec = 2;
330 break;
331
332 case 'd':
333 prec = 4;
334 break;
335
336 default:
337 *sizep = 0;
338 return "bad call to md_atof";
339 }
340
341 t = atof_ieee (input_line_pointer, type, words);
342 if (t)
343 input_line_pointer = t;
344
345 *sizep = prec * 2;
346
347 for (i = prec - 1; i >= 0; i--)
348 {
349 md_number_to_chars (litp, (valueT) words[i], 2);
350 litp += 2;
351 }
352
353 return NULL;
354 }
355
356
357 void
358 md_convert_frag (abfd, sec, fragP)
359 bfd *abfd;
360 asection *sec;
361 fragS *fragP;
362 {
363 /* printf ("call to md_convert_frag \n"); */
364 abort ();
365 }
366
367 valueT
368 md_section_align (seg, addr)
369 asection *seg;
370 valueT addr;
371 {
372 int align = bfd_get_section_alignment (stdoutput, seg);
373 return ((addr + (1 << align) - 1) & (-1 << align));
374 }
375
376 void
377 md_begin ()
378 {
379 char *prev_name = "";
380 register const struct mn10200_opcode *op;
381
382 mn10200_hash = hash_new();
383
384 /* Insert unique names into hash table. The MN10200 instruction set
385 has many identical opcode names that have different opcodes based
386 on the operands. This hash table then provides a quick index to
387 the first opcode with a particular name in the opcode table. */
388
389 op = mn10200_opcodes;
390 while (op->name)
391 {
392 if (strcmp (prev_name, op->name))
393 {
394 prev_name = (char *) op->name;
395 hash_insert (mn10200_hash, op->name, (char *) op);
396 }
397 op++;
398 }
399
400 /* This is both a simplification (we don't have to write md_apply_fix)
401 and support for future optimizations (branch shortening and similar
402 stuff in the linker. */
403 linkrelax = 1;
404 }
405
406 void
407 md_assemble (str)
408 char *str;
409 {
410 char *s;
411 struct mn10200_opcode *opcode;
412 struct mn10200_opcode *next_opcode;
413 const unsigned char *opindex_ptr;
414 int next_opindex;
415 unsigned long insn, extension, size = 0;
416 char *f;
417 int i;
418 int match;
419
420 /* Get the opcode. */
421 for (s = str; *s != '\0' && ! isspace (*s); s++)
422 ;
423 if (*s != '\0')
424 *s++ = '\0';
425
426 /* find the first opcode with the proper name */
427 opcode = (struct mn10200_opcode *)hash_find (mn10200_hash, str);
428 if (opcode == NULL)
429 {
430 as_bad ("Unrecognized opcode: `%s'", str);
431 return;
432 }
433
434 str = s;
435 while (isspace (*str))
436 ++str;
437
438 input_line_pointer = str;
439
440 for(;;)
441 {
442 const char *errmsg = NULL;
443 int op_idx;
444 char *hold;
445 int extra_shift = 0;
446
447 fc = 0;
448 match = 0;
449 next_opindex = 0;
450 insn = opcode->opcode;
451 extension = 0;
452 for (op_idx = 1, opindex_ptr = opcode->operands;
453 *opindex_ptr != 0;
454 opindex_ptr++, op_idx++)
455 {
456 const struct mn10200_operand *operand;
457 expressionS ex;
458
459 if (next_opindex == 0)
460 {
461 operand = &mn10200_operands[*opindex_ptr];
462 }
463 else
464 {
465 operand = &mn10200_operands[next_opindex];
466 next_opindex = 0;
467 }
468
469 errmsg = NULL;
470
471 while (*str == ' ' || *str == ',')
472 ++str;
473
474 /* Gather the operand. */
475 hold = input_line_pointer;
476 input_line_pointer = str;
477
478 if (operand->flags & MN10200_OPERAND_PAREN)
479 {
480 if (*input_line_pointer != ')' && *input_line_pointer != '(')
481 {
482 input_line_pointer = hold;
483 str = hold;
484 goto error;
485 }
486 input_line_pointer++;
487 goto keep_going;
488 }
489 /* See if we can match the operands. */
490 else if (operand->flags & MN10200_OPERAND_DREG)
491 {
492 if (!data_register_name (&ex))
493 {
494 input_line_pointer = hold;
495 str = hold;
496 goto error;
497 }
498 }
499 else if (operand->flags & MN10200_OPERAND_AREG)
500 {
501 if (!address_register_name (&ex))
502 {
503 input_line_pointer = hold;
504 str = hold;
505 goto error;
506 }
507 }
508 else if (operand->flags & MN10200_OPERAND_PSW)
509 {
510 char *start = input_line_pointer;
511 char c = get_symbol_end ();
512
513 if (strcmp (start, "psw") != 0)
514 {
515 *input_line_pointer = c;
516 input_line_pointer = hold;
517 str = hold;
518 goto error;
519 }
520 *input_line_pointer = c;
521 goto keep_going;
522 }
523 else if (operand->flags & MN10200_OPERAND_MDR)
524 {
525 char *start = input_line_pointer;
526 char c = get_symbol_end ();
527
528 if (strcmp (start, "mdr") != 0)
529 {
530 *input_line_pointer = c;
531 input_line_pointer = hold;
532 str = hold;
533 goto error;
534 }
535 *input_line_pointer = c;
536 goto keep_going;
537 }
538 else if (data_register_name (&ex))
539 {
540 input_line_pointer = hold;
541 str = hold;
542 goto error;
543 }
544 else if (address_register_name (&ex))
545 {
546 input_line_pointer = hold;
547 str = hold;
548 goto error;
549 }
550 else if (other_register_name (&ex))
551 {
552 input_line_pointer = hold;
553 str = hold;
554 goto error;
555 }
556 else if (*str == ')' || *str == '(')
557 {
558 input_line_pointer = hold;
559 str = hold;
560 goto error;
561 }
562 else
563 {
564 expression (&ex);
565 }
566
567 switch (ex.X_op)
568 {
569 case O_illegal:
570 errmsg = "illegal operand";
571 goto error;
572 case O_absent:
573 errmsg = "missing operand";
574 goto error;
575 case O_register:
576 if ((operand->flags
577 & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
578 {
579 input_line_pointer = hold;
580 str = hold;
581 goto error;
582 }
583
584 if (opcode->format == FMT_2 || opcode->format == FMT_5)
585 extra_shift = 8;
586 else if (opcode->format == FMT_3 || opcode->format == FMT_6
587 || opcode->format == FMT_7)
588 extra_shift = 16;
589 else
590 extra_shift = 0;
591
592 mn10200_insert_operand (&insn, &extension, operand,
593 ex.X_add_number, (char *) NULL,
594 0, extra_shift);
595
596 break;
597
598 case O_constant:
599 /* If this operand can be promoted, and it doesn't
600 fit into the allocated bitfield for this insn,
601 then promote it (ie this opcode does not match). */
602 if (operand->flags & MN10200_OPERAND_PROMOTE
603 && ! check_operand (insn, operand, ex.X_add_number))
604 {
605 input_line_pointer = hold;
606 str = hold;
607 goto error;
608 }
609
610 mn10200_insert_operand (&insn, &extension, operand,
611 ex.X_add_number, (char *) NULL,
612 0, 0);
613 break;
614
615 default:
616 /* If this operand can be promoted, then this opcode didn't
617 match since we can't know if it needed promotion! */
618 if (operand->flags & MN10200_OPERAND_PROMOTE)
619 {
620 input_line_pointer = hold;
621 str = hold;
622 goto error;
623 }
624
625 /* We need to generate a fixup for this expression. */
626 if (fc >= MAX_INSN_FIXUPS)
627 as_fatal ("too many fixups");
628 fixups[fc].exp = ex;
629 fixups[fc].opindex = *opindex_ptr;
630 fixups[fc].reloc = BFD_RELOC_UNUSED;
631 ++fc;
632 break;
633 }
634
635 keep_going:
636 str = input_line_pointer;
637 input_line_pointer = hold;
638
639 while (*str == ' ' || *str == ',')
640 ++str;
641
642 }
643
644 /* Make sure we used all the operands! */
645 if (*str != ',')
646 match = 1;
647
648 error:
649 if (match == 0)
650 {
651 next_opcode = opcode + 1;
652 if (!strcmp(next_opcode->name, opcode->name))
653 {
654 opcode = next_opcode;
655 continue;
656 }
657
658 as_bad ("%s", errmsg);
659 return;
660 }
661 break;
662 }
663
664 while (isspace (*str))
665 ++str;
666
667 if (*str != '\0')
668 as_bad ("junk at end of line: `%s'", str);
669
670 input_line_pointer = str;
671
672 if (opcode->format == FMT_1)
673 size = 1;
674 else if (opcode->format == FMT_2 || opcode->format == FMT_4)
675 size = 2;
676 else if (opcode->format == FMT_3 || opcode->format == FMT_5)
677 size = 3;
678 else if (opcode->format == FMT_6)
679 size = 4;
680 else if (opcode->format == FMT_7)
681 size = 5;
682 else
683 abort ();
684
685 /* Write out the instruction. */
686
687 f = frag_more (size);
688
689 /* Oh, what a mess. The instruction is in big endian format, but
690 16 and 24bit immediates are little endian! */
691 if (opcode->format == FMT_3)
692 {
693 number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
694 number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
695 }
696 else if (opcode->format == FMT_6)
697 {
698 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
699 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
700 }
701 else if (opcode->format == FMT_7)
702 {
703 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
704 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
705 number_to_chars_littleendian (f + 4, extension & 0xff, 1);
706 }
707 else
708 {
709 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
710 }
711
712 /* Create any fixups. */
713 for (i = 0; i < fc; i++)
714 {
715 const struct mn10200_operand *operand;
716
717 operand = &mn10200_operands[fixups[i].opindex];
718 if (fixups[i].reloc != BFD_RELOC_UNUSED)
719 {
720 reloc_howto_type *reloc_howto;
721 int size;
722 int offset;
723 fixS *fixP;
724
725 reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
726
727 if (!reloc_howto)
728 abort();
729
730 size = bfd_get_reloc_size (reloc_howto);
731
732 if (size < 1 || size > 4)
733 abort();
734
735 offset = 4 - size;
736 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
737 &fixups[i].exp,
738 reloc_howto->pc_relative,
739 fixups[i].reloc);
740 }
741 else
742 {
743 int reloc, pcrel, reloc_size, offset;
744
745 reloc = BFD_RELOC_NONE;
746 /* How big is the reloc? Remember SPLIT relocs are
747 implicitly 32bits. */
748 reloc_size = operand->bits;
749
750 offset = size - reloc_size / 8;
751
752 /* Is the reloc pc-relative? */
753 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
754
755
756 /* Choose a proper BFD relocation type. */
757 if (pcrel)
758 {
759 if (reloc_size == 8)
760 reloc = BFD_RELOC_8_PCREL;
761 else if (reloc_size == 24)
762 reloc = BFD_RELOC_24_PCREL;
763 else
764 abort ();
765 }
766 else
767 {
768 if (reloc_size == 32)
769 reloc = BFD_RELOC_32;
770 else if (reloc_size == 16)
771 reloc = BFD_RELOC_16;
772 else if (reloc_size == 8)
773 reloc = BFD_RELOC_8;
774 else if (reloc_size == 24)
775 reloc = BFD_RELOC_24;
776 else
777 abort ();
778 }
779
780 /* Convert the size of the reloc into what fix_new_exp wants. */
781 reloc_size = reloc_size / 8;
782 if (reloc_size == 8)
783 reloc_size = 0;
784 else if (reloc_size == 16)
785 reloc_size = 1;
786 else if (reloc_size == 32 || reloc_size == 24)
787 reloc_size = 2;
788
789 fix_new_exp (frag_now, f - frag_now->fr_literal + offset, reloc_size,
790 &fixups[i].exp, pcrel,
791 ((bfd_reloc_code_real_type) reloc));
792 }
793 }
794 }
795
796
797 /* if while processing a fixup, a reloc really needs to be created */
798 /* then it is done here */
799
800 arelent *
801 tc_gen_reloc (seg, fixp)
802 asection *seg;
803 fixS *fixp;
804 {
805 arelent *reloc;
806 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
807 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
808 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
809 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
810 if (reloc->howto == (reloc_howto_type *) NULL)
811 {
812 as_bad_where (fixp->fx_file, fixp->fx_line,
813 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
814 return NULL;
815 }
816 reloc->addend = fixp->fx_offset;
817 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
818 return reloc;
819 }
820
821 int
822 md_estimate_size_before_relax (fragp, seg)
823 fragS *fragp;
824 asection *seg;
825 {
826 return 0;
827 }
828
829 long
830 md_pcrel_from (fixp)
831 fixS *fixp;
832 {
833 return fixp->fx_frag->fr_address;
834 #if 0
835 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
836 {
837 /* The symbol is undefined. Let the linker figure it out. */
838 return 0;
839 }
840 return fixp->fx_frag->fr_address + fixp->fx_where;
841 #endif
842 }
843
844 int
845 md_apply_fix3 (fixp, valuep, seg)
846 fixS *fixp;
847 valueT *valuep;
848 segT seg;
849 {
850 /* We shouldn't ever get here because linkrelax is nonzero. */
851 abort ();
852 fixp->fx_done = 1;
853 return 0;
854 }
855
856 /* Insert an operand value into an instruction. */
857
858 static void
859 mn10200_insert_operand (insnp, extensionp, operand, val, file, line, shift)
860 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
889 if (test < (offsetT) min || test > (offsetT) max)
890 {
891 const char *err =
892 "operand out of range (%s not between %ld and %ld)";
893 char buf[100];
894
895 sprint_value (buf, test);
896 if (file == (char *) NULL)
897 as_warn (err, buf, min, max);
898 else
899 as_warn_where (file, line, err, buf, min, max);
900 }
901 }
902
903 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
904 {
905 *insnp |= (((long) val & ((1 << operand->bits) - 1))
906 << (operand->shift + shift));
907
908 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
909 *insnp |= (((long) val & ((1 << operand->bits) - 1))
910 << (operand->shift + shift + 2));
911 }
912 else
913 {
914 *extensionp |= (val >> 16) & 0xff;
915 *insnp |= val & 0xffff;
916 }
917 }
918
919 static unsigned long
920 check_operand (insn, operand, val)
921 unsigned long insn;
922 const struct mn10200_operand *operand;
923 offsetT val;
924 {
925 /* No need to check 24bit or 32bit operands for a bit. */
926 if (operand->bits < 24
927 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
928 {
929 long min, max;
930 offsetT test;
931
932 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
933 {
934 max = (1 << (operand->bits - 1)) - 1;
935 min = - (1 << (operand->bits - 1));
936 }
937 else
938 {
939 max = (1 << operand->bits) - 1;
940 min = 0;
941 }
942
943 test = val;
944
945
946 if (test < (offsetT) min || test > (offsetT) max)
947 return 0;
948 else
949 return 1;
950 }
951 return 1;
952 }