* mn10300.h (MN10300_OPERAND_PAREN): Define.
[deliverable/binutils-gdb.git] / gas / config / tc-mn10300.c
CommitLineData
ae1b99e4 1/* tc-mn10300.c -- Assembler code for the Matsushita 10300
0f91d763
JL
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"
ae1b99e4 26#include "opcode/mn10300.h"
0f91d763
JL
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 */
ae1b99e4
JL
57static unsigned long mn10300
58 PARAMS ((unsigned long insn, const struct mn10300_operand *operand,
0f91d763
JL
59 offsetT val, char *file, unsigned int line));
60static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
61static boolean register_name PARAMS ((expressionS *expressionP));
62static boolean system_register_name PARAMS ((expressionS *expressionP));
63static boolean cc_name PARAMS ((expressionS *expressionP));
0f91d763
JL
64
65
66/* fixups */
67#define MAX_INSN_FIXUPS (5)
ae1b99e4 68struct mn10300_fixup
0f91d763
JL
69{
70 expressionS exp;
71 int opindex;
72 bfd_reloc_code_real_type reloc;
73};
ae1b99e4 74struct mn10300_fixup fixups[MAX_INSN_FIXUPS];
0f91d763
JL
75static int fc;
76\f
77const char *md_shortopts = "";
78struct option md_longopts[] = {
79 {NULL, no_argument, NULL, 0}
80};
81size_t md_longopts_size = sizeof(md_longopts);
82
83/* The target specific pseudo-ops which we support. */
84const pseudo_typeS md_pseudo_table[] =
85{
86 { NULL, NULL, 0 }
87};
88
89/* Opcode hash table. */
ae1b99e4 90static struct hash_control *mn10300_hash;
0f91d763
JL
91
92/* This table is sorted. Suitable for searching by a binary search. */
1217102f 93static const struct reg_name data_registers[] =
0f91d763 94{
1217102f
JL
95 { "d0", 0 },
96 { "d1", 1 },
97 { "d2", 2 },
98 { "d3", 3 },
0f91d763 99};
1217102f 100#define DATA_REG_NAME_CNT (sizeof(data_registers) / sizeof(struct reg_name))
0f91d763 101
1217102f 102static const struct reg_name address_registers[] =
0f91d763 103{
1217102f
JL
104 { "a0", 0 },
105 { "a1", 1 },
106 { "a2", 2 },
107 { "a3", 3 },
0f91d763 108};
1217102f 109#define ADDRESS_REG_NAME_CNT (sizeof(address_registers) / sizeof(struct reg_name))
0f91d763 110
1217102f 111static const struct reg_name other_registers[] =
0f91d763 112{
1217102f
JL
113 { "mdr", 0 },
114 { "psw", 0 },
115 { "sp", 0 },
0f91d763 116};
1217102f 117#define OTHER_REG_NAME_CNT (sizeof(other_registers) / sizeof(struct reg_name))
0f91d763
JL
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
123static int
124reg_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 */
161static boolean
1217102f 162data_register_name (expressionP)
0f91d763
JL
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 ();
1217102f 174 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
0f91d763
JL
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
1217102f 197/* Summary of register_name().
0f91d763
JL
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 */
207static boolean
1217102f 208address_register_name (expressionP)
0f91d763
JL
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 ();
1217102f 220 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
0f91d763
JL
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
1217102f 243/* Summary of register_name().
0f91d763
JL
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 */
253static boolean
1217102f 254other_register_name (expressionP)
0f91d763
JL
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 ();
1217102f 266 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
0f91d763
JL
267
268 /* look to see if it's in the register table */
269 if (reg_number >= 0)
270 {
1217102f 271 expressionP->X_op = O_register;
0f91d763
JL
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
289void
290md_show_usage (stream)
291 FILE *stream;
292{
ae1b99e4 293 fprintf(stream, "MN10300 options:\n\
0f91d763
JL
294none yet\n");
295}
296
297int
298md_parse_option (c, arg)
299 int c;
300 char *arg;
301{
302 return 0;
303}
304
305symbolS *
306md_undefined_symbol (name)
307 char *name;
308{
309 return 0;
310}
311
312char *
313md_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
354void
355md_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
364valueT
365md_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
373void
374md_begin ()
375{
376 char *prev_name = "";
ae1b99e4 377 register const struct mn10300_opcode *op;
0f91d763 378
ae1b99e4 379 mn10300_hash = hash_new();
0f91d763 380
ae1b99e4 381 /* Insert unique names into hash table. The MN10300 instruction set
0f91d763
JL
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
ae1b99e4 386 op = mn10300_opcodes;
0f91d763
JL
387 while (op->name)
388 {
389 if (strcmp (prev_name, op->name))
390 {
391 prev_name = (char *) op->name;
ae1b99e4 392 hash_insert (mn10300_hash, op->name, (char *) op);
0f91d763
JL
393 }
394 op++;
395 }
396}
397
0f91d763
JL
398void
399md_assemble (str)
400 char *str;
401{
402 char *s;
ae1b99e4
JL
403 struct mn10300_opcode *opcode;
404 struct mn10300_opcode *next_opcode;
0f91d763
JL
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 */
ae1b99e4 420 opcode = (struct mn10300_opcode *)hash_find (mn10300_hash, str);
0f91d763
JL
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;
1217102f
JL
436 int op_idx;
437 int parens = 0;
438 char *hold;
0f91d763
JL
439
440 fc = 0;
441 match = 0;
442 next_opindex = 0;
443 insn = opcode->opcode;
1217102f
JL
444 for (op_idx = 1, opindex_ptr = opcode->operands;
445 *opindex_ptr != 0;
446 opindex_ptr++, op_idx++)
0f91d763 447 {
ae1b99e4 448 const struct mn10300_operand *operand;
0f91d763
JL
449 expressionS ex;
450
451 if (next_opindex == 0)
452 {
ae1b99e4 453 operand = &mn10300_operands[*opindex_ptr];
0f91d763
JL
454 }
455 else
456 {
ae1b99e4 457 operand = &mn10300_operands[next_opindex];
0f91d763
JL
458 next_opindex = 0;
459 }
460
461 errmsg = NULL;
462
463 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
464 ++str;
465
466 /* Gather the operand. */
467 hold = input_line_pointer;
468 input_line_pointer = str;
469
1217102f
JL
470#if 1
471 if (*str == '(')
472 {
473 str++;
474 input_line_pointer++;
475 parens++;
476 }
477#endif
478 /* See if we can match the operands. */
479 if (operand->flags & MN10300_OPERAND_DREG)
0f91d763 480 {
1217102f 481 if (!data_register_name (&ex))
0f91d763 482 {
1217102f
JL
483 input_line_pointer = hold;
484 str = hold;
0f91d763
JL
485 goto error;
486 }
1217102f
JL
487 }
488 else if (operand->flags & MN10300_OPERAND_AREG)
489 {
490 if (!address_register_name (&ex))
0f91d763 491 {
1217102f
JL
492 input_line_pointer = hold;
493 str = hold;
494 goto error;
0f91d763 495 }
1217102f
JL
496 }
497 else if (operand->flags & MN10300_OPERAND_SP)
498 {
499 char *start = input_line_pointer;
500 char c = get_symbol_end ();
501
502 if (strcmp (start, "sp") != 0)
503 {
504 *input_line_pointer = c;
505 input_line_pointer = hold;
506 str = hold;
507 goto error;
508 }
509 *input_line_pointer = c;
510 goto keep_going;
511 }
512 else if (operand->flags & MN10300_OPERAND_PSW)
513 {
514 char *start = input_line_pointer;
515 char c = get_symbol_end ();
516
517 if (strcmp (start, "psw") != 0)
0f91d763 518 {
1217102f
JL
519 *input_line_pointer = c;
520 input_line_pointer = hold;
521 str = hold;
522 goto error;
523 }
524 *input_line_pointer = c;
525 goto keep_going;
526 }
527 else if (operand->flags & MN10300_OPERAND_MDR)
528 {
529 char *start = input_line_pointer;
530 char c = get_symbol_end ();
0f91d763 531
1217102f
JL
532 if (strcmp (start, "mdr") != 0)
533 {
534 *input_line_pointer = c;
535 input_line_pointer = hold;
536 str = hold;
537 goto error;
0f91d763 538 }
1217102f
JL
539 *input_line_pointer = c;
540 goto keep_going;
541 }
542 else if (data_register_name (&ex))
543 {
544 input_line_pointer = hold;
545 str = hold;
546 goto error;
547 }
548 else if (address_register_name (&ex))
549 {
550 input_line_pointer = hold;
551 str = hold;
552 goto error;
553 }
554 else if (other_register_name (&ex))
555 {
556 input_line_pointer = hold;
557 str = hold;
558 goto error;
0f91d763
JL
559 }
560 else
561 {
1217102f
JL
562 expression (&ex);
563 }
564
0f91d763
JL
565 switch (ex.X_op)
566 {
567 case O_illegal:
568 errmsg = "illegal operand";
569 goto error;
570 case O_absent:
571 errmsg = "missing operand";
572 goto error;
573 case O_register:
1217102f
JL
574 if (operand->flags & (MN10300_OPERAND_DREG
575 | MN10300_OPERAND_AREG) == 0)
576 {
577 input_line_pointer = hold;
578 str = hold;
579 goto error;
580 }
0f91d763 581
ae1b99e4 582 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
583 (char *) NULL, 0);
584 break;
585
586 case O_constant:
1217102f
JL
587 /* If this operand can be promoted, and it doesn't
588 fit into the allocated bitfield for this insn,
589 then promote it (ie this opcode does not match). */
590 if (operand->flags & MN10300_OPERAND_PROMOTE
591 && ! check_operand (insn, operand, ex.X_add_number))
592 {
593 input_line_pointer = hold;
594 str = hold;
595 goto error;
596 }
597
ae1b99e4 598 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
599 (char *) NULL, 0);
600 break;
601
602 default:
1217102f
JL
603 /* If this operand can be promoted, then this opcode didn't
604 match since we can't know if it needed promotion! */
605 if (operand->flags & MN10300_OPERAND_PROMOTE)
606 {
607 input_line_pointer = hold;
608 str = hold;
609 goto error;
610 }
611
0f91d763
JL
612 /* We need to generate a fixup for this expression. */
613 if (fc >= MAX_INSN_FIXUPS)
614 as_fatal ("too many fixups");
615 fixups[fc].exp = ex;
616 fixups[fc].opindex = *opindex_ptr;
617 fixups[fc].reloc = BFD_RELOC_UNUSED;
618 ++fc;
619 break;
620 }
621
1217102f 622keep_going:
0f91d763
JL
623 str = input_line_pointer;
624 input_line_pointer = hold;
625
626 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
627 ++str;
1217102f
JL
628
629 if (*str == ')')
630 {
631 str++;
632 parens--;
633 }
634 }
635 if (parens == 0 && *str != ',')
636 match = 1;
637 else
638 {
639 input_line_pointer = hold;
640 str = hold;
0f91d763 641 }
0f91d763
JL
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
1217102f
JL
667 /* XXX */
668 if (opcode->format == 1)
669 size = 1;
0f91d763 670
1217102f 671 if (opcode->format == 2 || opcode->format == 6)
0f91d763 672 size = 2;
0f91d763 673
1217102f
JL
674 if (opcode->format == 3 || opcode->format == 7)
675 size = 3;
0f91d763 676
1217102f
JL
677 if (opcode->format == 4)
678 size = 5;
0f91d763 679
1217102f
JL
680 if (opcode->format == 5)
681 size = 7;
0f91d763 682
1217102f
JL
683 if (opcode->format == 8)
684 size = 4;
0f91d763 685
1217102f
JL
686 if (opcode->format == 9)
687 size = 6;
688
689 if (opcode->format == 10)
690 size = 8;
691
692
693 /* Write out the instruction. */
694
695 f = frag_more (size);
696 if (size > 4)
697 size = 4;
698 md_number_to_chars (f, insn, size);
0f91d763
JL
699}
700
701
702/* if while processing a fixup, a reloc really needs to be created */
703/* then it is done here */
704
705arelent *
706tc_gen_reloc (seg, fixp)
707 asection *seg;
708 fixS *fixp;
709{
710 arelent *reloc;
711 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
712 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
713 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
714 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
715 if (reloc->howto == (reloc_howto_type *) NULL)
716 {
717 as_bad_where (fixp->fx_file, fixp->fx_line,
718 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
719 return NULL;
720 }
721 reloc->addend = fixp->fx_addnumber;
722 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
723 return reloc;
724}
725
726int
727md_estimate_size_before_relax (fragp, seg)
728 fragS *fragp;
729 asection *seg;
730{
731 return 0;
732}
733
734long
735md_pcrel_from (fixp)
736 fixS *fixp;
737{
738 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
739 {
740 /* The symbol is undefined. Let the linker figure it out. */
741 return 0;
742 }
743 return fixp->fx_frag->fr_address + fixp->fx_where;
744}
745
746int
747md_apply_fix3 (fixp, valuep, seg)
748 fixS *fixp;
749 valueT *valuep;
750 segT seg;
751{
752 valueT value;
753 char *where;
754
1217102f
JL
755 fixp->fx_done = 1;
756 return 0;
757
0f91d763
JL
758 if (fixp->fx_addsy == (symbolS *) NULL)
759 {
760 value = *valuep;
761 fixp->fx_done = 1;
762 }
763 else if (fixp->fx_pcrel)
764 value = *valuep;
765 else
766 {
767 value = fixp->fx_offset;
768 if (fixp->fx_subsy != (symbolS *) NULL)
769 {
770 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
771 value -= S_GET_VALUE (fixp->fx_subsy);
772 else
773 {
774 /* We don't actually support subtracting a symbol. */
775 as_bad_where (fixp->fx_file, fixp->fx_line,
776 "expression too complex");
777 }
778 }
779 }
780
781 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
782
783 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
784 {
785 int opindex;
ae1b99e4 786 const struct mn10300_operand *operand;
0f91d763
JL
787 char *where;
788 unsigned long insn;
789
790 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
ae1b99e4 791 operand = &mn10300_operands[opindex];
0f91d763
JL
792
793 /* Fetch the instruction, insert the fully resolved operand
794 value, and stuff the instruction back again.
795
796 Note the instruction has been stored in little endian
797 format! */
798 where = fixp->fx_frag->fr_literal + fixp->fx_where;
799
800 insn = bfd_getl32((unsigned char *) where);
ae1b99e4 801 insn = mn10300_insert_operand (insn, operand, (offsetT) value,
0f91d763
JL
802 fixp->fx_file, fixp->fx_line);
803 bfd_putl32((bfd_vma) insn, (unsigned char *) where);
804
805 if (fixp->fx_done)
806 {
807 /* Nothing else to do here. */
808 return 1;
809 }
810
811 /* Determine a BFD reloc value based on the operand information.
812 We are only prepared to turn a few of the operands into relocs. */
813
814 {
815 as_bad_where(fixp->fx_file, fixp->fx_line,
816 "unresolved expression that must be resolved");
817 fixp->fx_done = 1;
818 return 1;
819 }
820 }
821 else if (fixp->fx_done)
822 {
823 /* We still have to insert the value into memory! */
824 where = fixp->fx_frag->fr_literal + fixp->fx_where;
825 if (fixp->fx_size == 1)
826 *where = value & 0xff;
827 if (fixp->fx_size == 2)
828 bfd_putl16(value & 0xffff, (unsigned char *) where);
829 if (fixp->fx_size == 4)
830 bfd_putl32(value, (unsigned char *) where);
831 }
832
833 fixp->fx_addnumber = value;
834 return 1;
835}
836
0f91d763
JL
837/* Insert an operand value into an instruction. */
838
839static unsigned long
ae1b99e4 840mn10300_insert_operand (insn, operand, val, file, line)
0f91d763 841 unsigned long insn;
ae1b99e4 842 const struct mn10300_operand *operand;
0f91d763
JL
843 offsetT val;
844 char *file;
845 unsigned int line;
846{
1217102f 847 if (operand->bits != 32)
0f91d763
JL
848 {
849 long min, max;
850 offsetT test;
851
1217102f
JL
852 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
853 {
854 max = (1 << (operand->bits - 1)) - 1;
855 min = - (1 << (operand->bits - 1));
856 }
857 else
0f91d763
JL
858 {
859 max = (1 << operand->bits) - 1;
860 min = 0;
861 }
862
863 test = val;
864
865
866 if (test < (offsetT) min || test > (offsetT) max)
867 {
868 const char *err =
869 "operand out of range (%s not between %ld and %ld)";
870 char buf[100];
871
872 sprint_value (buf, test);
873 if (file == (char *) NULL)
874 as_warn (err, buf, min, max);
875 else
876 as_warn_where (file, line, err, buf, min, max);
877 }
878 }
879
880 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
881 return insn;
882}
1217102f
JL
883
884static unsigned long
885check_operand (insn, operand, val)
886 unsigned long insn;
887 const struct mn10300_operand *operand;
888 offsetT val;
889{
890 if (operand->bits != 32)
891 {
892 long min, max;
893 offsetT test;
894
895 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
896 {
897 max = (1 << (operand->bits - 1)) - 1;
898 min = - (1 << (operand->bits - 1));
899 }
900 else
901 {
902 max = (1 << operand->bits) - 1;
903 min = 0;
904 }
905
906 test = val;
907
908
909 if (test < (offsetT) min || test > (offsetT) max)
910 return 0;
911 else
912 return 1;
913 }
914 return 1;
915}
This page took 0.059917 seconds and 4 git commands to generate.