* config/tc-mn10300.h (md_assemble): Tweak further so
[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 436 int op_idx;
1217102f 437 char *hold;
0f91d763
JL
438
439 fc = 0;
440 match = 0;
441 next_opindex = 0;
442 insn = opcode->opcode;
1217102f
JL
443 for (op_idx = 1, opindex_ptr = opcode->operands;
444 *opindex_ptr != 0;
445 opindex_ptr++, op_idx++)
0f91d763 446 {
ae1b99e4 447 const struct mn10300_operand *operand;
0f91d763
JL
448 expressionS ex;
449
450 if (next_opindex == 0)
451 {
ae1b99e4 452 operand = &mn10300_operands[*opindex_ptr];
0f91d763
JL
453 }
454 else
455 {
ae1b99e4 456 operand = &mn10300_operands[next_opindex];
0f91d763
JL
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
a6be605a
JL
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 }
1217102f 477 input_line_pointer++;
a6be605a 478 goto keep_going;
1217102f 479 }
1217102f 480 /* See if we can match the operands. */
a6be605a 481 else if (operand->flags & MN10300_OPERAND_DREG)
0f91d763 482 {
1217102f 483 if (!data_register_name (&ex))
0f91d763 484 {
1217102f
JL
485 input_line_pointer = hold;
486 str = hold;
0f91d763
JL
487 goto error;
488 }
1217102f
JL
489 }
490 else if (operand->flags & MN10300_OPERAND_AREG)
491 {
492 if (!address_register_name (&ex))
0f91d763 493 {
1217102f
JL
494 input_line_pointer = hold;
495 str = hold;
496 goto error;
0f91d763 497 }
1217102f
JL
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)
0f91d763 520 {
1217102f
JL
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 ();
0f91d763 533
1217102f
JL
534 if (strcmp (start, "mdr") != 0)
535 {
536 *input_line_pointer = c;
537 input_line_pointer = hold;
538 str = hold;
539 goto error;
0f91d763 540 }
1217102f
JL
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;
0f91d763 561 }
a6be605a
JL
562 else if (*str == ')' || *str == '(')
563 {
564 input_line_pointer = hold;
565 str = hold;
566 goto error;
567 }
0f91d763
JL
568 else
569 {
1217102f
JL
570 expression (&ex);
571 }
572
0f91d763
JL
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:
1217102f
JL
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 }
0f91d763 589
ae1b99e4 590 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
591 (char *) NULL, 0);
592 break;
593
594 case O_constant:
1217102f
JL
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
ae1b99e4 606 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
607 (char *) NULL, 0);
608 break;
609
610 default:
1217102f
JL
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
0f91d763
JL
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
1217102f 630keep_going:
0f91d763
JL
631 str = input_line_pointer;
632 input_line_pointer = hold;
633
634 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
635 ++str;
1217102f 636
1217102f 637 }
a6be605a
JL
638
639 /* Make sure we used all the operands! */
640 if (*str != ',')
1217102f 641 match = 1;
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.061555 seconds and 4 git commands to generate.