* config/tc-mn10200.c (mn10200_insert_operand): Don't
[deliverable/binutils-gdb.git] / gas / config / tc-mn10200.c
CommitLineData
dc1f8a21
JL
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. */
29struct 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. */
38const char comment_chars[] = "#";
39
40/* Characters which start a comment at the beginning of a line. */
41const char line_comment_chars[] = ";#";
42
43/* Characters which may be used to separate multiple commands on a
44 single line. */
45const char line_separator_chars[] = ";";
46
47/* Characters which are used to indicate an exponent in a floating
48 point number. */
49const char EXP_CHARS[] = "eE";
50
51/* Characters which mean that a number is a floating point constant,
52 as in 0d1.0. */
53const char FLT_CHARS[] = "dD";
54\f
55
56/* local functions */
57static void mn10200_insert_operand PARAMS ((unsigned long *, unsigned long *,
58 const struct mn10200_operand *,
59 offsetT, char *, unsigned,
60 unsigned));
61static unsigned long check_operand PARAMS ((unsigned long,
62 const struct mn10200_operand *,
63 offsetT));
64static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
65static boolean data_register_name PARAMS ((expressionS *expressionP));
66static boolean address_register_name PARAMS ((expressionS *expressionP));
67static boolean other_register_name PARAMS ((expressionS *expressionP));
68
69
70/* fixups */
71#define MAX_INSN_FIXUPS (5)
72struct mn10200_fixup
73{
74 expressionS exp;
75 int opindex;
76 bfd_reloc_code_real_type reloc;
77};
78struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
79static int fc;
80\f
81const char *md_shortopts = "";
82struct option md_longopts[] = {
83 {NULL, no_argument, NULL, 0}
84};
85size_t md_longopts_size = sizeof(md_longopts);
86
87/* The target specific pseudo-ops which we support. */
88const pseudo_typeS md_pseudo_table[] =
89{
90 { NULL, NULL, 0 }
91};
92
93/* Opcode hash table. */
94static struct hash_control *mn10200_hash;
95
96/* This table is sorted. Suitable for searching by a binary search. */
97static 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
106static 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
115static 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
126static int
127reg_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 */
164static boolean
165data_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 */
210static boolean
211address_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 */
256static boolean
257other_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
292void
293md_show_usage (stream)
294 FILE *stream;
295{
296 fprintf(stream, "MN10200 options:\n\
297none yet\n");
298}
299
300int
301md_parse_option (c, arg)
302 int c;
303 char *arg;
304{
305 return 0;
306}
307
308symbolS *
309md_undefined_symbol (name)
310 char *name;
311{
312 return 0;
313}
314
315char *
316md_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
357void
358md_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
367valueT
368md_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
376void
377md_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
406void
407md_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
635keep_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;
d4ba37af 652 if (!strcmp(next_opcode->name, opcode->name))
dc1f8a21
JL
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#if 0
713 /* Create any fixups. */
714 for (i = 0; i < fc; i++)
715 {
716 const struct mn10200_operand *operand;
717
718 operand = &mn10200_operands[fixups[i].opindex];
719 if (fixups[i].reloc != BFD_RELOC_UNUSED)
720 {
721 reloc_howto_type *reloc_howto;
722 int size;
723 int offset;
724 fixS *fixP;
725
726 reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
727
728 if (!reloc_howto)
729 abort();
730
731 size = bfd_get_reloc_size (reloc_howto);
732
733 if (size < 1 || size > 4)
734 abort();
735
736 offset = 4 - size;
737 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
738 &fixups[i].exp,
739 reloc_howto->pc_relative,
740 fixups[i].reloc);
741 }
742 else
743 {
744 int reloc, pcrel, reloc_size, offset;
745
746 reloc = BFD_RELOC_NONE;
747 /* How big is the reloc? Remember SPLIT relocs are
748 implicitly 32bits. */
749 reloc_size = operand->bits;
750
751 /* Is the reloc pc-relative? */
752 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
753
754 /* Gross. This disgusting hack is to make sure we
755 get the right offset for the 16/32 bit reloc in
756 "call" instructions. Basically they're a pain
757 because the reloc isn't at the end of the instruction. */
758 if ((size == 5 || size == 7)
759 && (((insn >> 24) & 0xff) == 0xcd
760 || ((insn >> 24) & 0xff) == 0xdd))
761 size -= 2;
762
763 /* Similarly for certain bit instructions which don't
764 hav their 32bit reloc at the tail of the instruction. */
765 if (size == 7
766 && (((insn >> 16) & 0xffff) == 0xfe00
767 || ((insn >> 16) & 0xffff) == 0xfe01
768 || ((insn >> 16) & 0xffff) == 0xfe02))
769 size -= 1;
770
771 offset = size - reloc_size / 8;
772
773 /* Choose a proper BFD relocation type. */
774 if (pcrel)
775 {
776 if (size == 6)
777 reloc = BFD_RELOC_MN10200_32_PCREL;
778 else if (size == 4)
779 reloc = BFD_RELOC_MN10200_16_PCREL;
780 else if (reloc_size == 32)
781 reloc = BFD_RELOC_32_PCREL;
782 else if (reloc_size == 16)
783 reloc = BFD_RELOC_16_PCREL;
784 else if (reloc_size == 8)
785 reloc = BFD_RELOC_8_PCREL;
786 else
787 abort ();
788 }
789 else
790 {
791 if (reloc_size == 32)
792 reloc = BFD_RELOC_MN10200_32B;
793 else if (reloc_size == 16)
794 reloc = BFD_RELOC_MN10200_16B;
795 else if (reloc_size == 8)
796 reloc = BFD_RELOC_8;
797 else
798 abort ();
799 }
800
801 /* Convert the size of the reloc into what fix_new_exp wants. */
802 reloc_size = reloc_size / 8;
803 if (reloc_size == 8)
804 reloc_size = 0;
805 else if (reloc_size == 16)
806 reloc_size = 1;
807 else if (reloc_size == 32)
808 reloc_size = 2;
809
810 fix_new_exp (frag_now, f - frag_now->fr_literal + offset, reloc_size,
811 &fixups[i].exp, pcrel,
812 ((bfd_reloc_code_real_type) reloc));
813 }
814 }
815#endif
816}
817
818
819/* if while processing a fixup, a reloc really needs to be created */
820/* then it is done here */
821
822arelent *
823tc_gen_reloc (seg, fixp)
824 asection *seg;
825 fixS *fixp;
826{
827 arelent *reloc;
828 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
829 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
830 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
831 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
832 if (reloc->howto == (reloc_howto_type *) NULL)
833 {
834 as_bad_where (fixp->fx_file, fixp->fx_line,
835 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
836 return NULL;
837 }
838 reloc->addend = fixp->fx_offset;
839 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
840 return reloc;
841}
842
843int
844md_estimate_size_before_relax (fragp, seg)
845 fragS *fragp;
846 asection *seg;
847{
848 return 0;
849}
850
851long
852md_pcrel_from (fixp)
853 fixS *fixp;
854{
855 return fixp->fx_frag->fr_address;
856#if 0
857 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
858 {
859 /* The symbol is undefined. Let the linker figure it out. */
860 return 0;
861 }
862 return fixp->fx_frag->fr_address + fixp->fx_where;
863#endif
864}
865
866int
867md_apply_fix3 (fixp, valuep, seg)
868 fixS *fixp;
869 valueT *valuep;
870 segT seg;
871{
872 /* We shouldn't ever get here because linkrelax is nonzero. */
873 abort ();
874 fixp->fx_done = 1;
875 return 0;
876}
877
878/* Insert an operand value into an instruction. */
879
880static void
881mn10200_insert_operand (insnp, extensionp, operand, val, file, line, shift)
882 unsigned long *insnp;
883 unsigned long *extensionp;
884 const struct mn10200_operand *operand;
885 offsetT val;
886 char *file;
887 unsigned int line;
888 unsigned int shift;
889{
d4ba37af
JL
890 /* No need to check 24 or 32bit operands for a bit. */
891 if (operand->bits < 24)
dc1f8a21
JL
892 {
893 long min, max;
894 offsetT test;
895
896 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
897 {
898 max = (1 << (operand->bits - 1)) - 1;
899 min = - (1 << (operand->bits - 1));
900 }
901 else
902 {
903 max = (1 << operand->bits) - 1;
904 min = 0;
905 }
906
907 test = val;
908
909
910 if (test < (offsetT) min || test > (offsetT) max)
911 {
912 const char *err =
913 "operand out of range (%s not between %ld and %ld)";
914 char buf[100];
915
916 sprint_value (buf, test);
917 if (file == (char *) NULL)
918 as_warn (err, buf, min, max);
919 else
920 as_warn_where (file, line, err, buf, min, max);
921 }
922 }
923
924 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
925 {
926 *insnp |= (((long) val & ((1 << operand->bits) - 1))
927 << (operand->shift + shift));
928
929 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
930 *insnp |= (((long) val & ((1 << operand->bits) - 1))
931 << (operand->shift + shift + 2));
932 }
933 else
934 {
935 *extensionp |= (val >> 16) & 0xff;
936 *insnp |= val & 0xffff;
937 }
938}
939
940static unsigned long
941check_operand (insn, operand, val)
942 unsigned long insn;
943 const struct mn10200_operand *operand;
944 offsetT val;
945{
d4ba37af
JL
946 /* No need to check 24bit or 32bit operands for a bit. */
947 if (operand->bits < 24)
dc1f8a21
JL
948 {
949 long min, max;
950 offsetT test;
951
952 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
953 {
954 max = (1 << (operand->bits - 1)) - 1;
955 min = - (1 << (operand->bits - 1));
956 }
957 else
958 {
959 max = (1 << operand->bits) - 1;
960 min = 0;
961 }
962
963 test = val;
964
965
966 if (test < (offsetT) min || test > (offsetT) max)
967 return 0;
968 else
969 return 1;
970 }
971 return 1;
972}
This page took 0.056691 seconds and 4 git commands to generate.