Dummy .Sanitize files. Should also fix snapshot problems.
[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));
ae1b99e4 64static bfd_reloc_code_real_type mn10300_reloc_prefix PARAMS ((void));
0f91d763
JL
65
66
67/* fixups */
68#define MAX_INSN_FIXUPS (5)
ae1b99e4 69struct mn10300_fixup
0f91d763
JL
70{
71 expressionS exp;
72 int opindex;
73 bfd_reloc_code_real_type reloc;
74};
ae1b99e4 75struct mn10300_fixup fixups[MAX_INSN_FIXUPS];
0f91d763
JL
76static int fc;
77\f
78const char *md_shortopts = "";
79struct option md_longopts[] = {
80 {NULL, no_argument, NULL, 0}
81};
82size_t md_longopts_size = sizeof(md_longopts);
83
84/* The target specific pseudo-ops which we support. */
85const pseudo_typeS md_pseudo_table[] =
86{
87 { NULL, NULL, 0 }
88};
89
90/* Opcode hash table. */
ae1b99e4 91static struct hash_control *mn10300_hash;
0f91d763
JL
92
93/* This table is sorted. Suitable for searching by a binary search. */
94static const struct reg_name pre_defined_registers[] =
95{
96 { "ep", 30 }, /* ep - element ptr */
97 { "gp", 4 }, /* gp - global ptr */
98 { "lp", 31 }, /* lp - link ptr */
99 { "r0", 0 },
100 { "r1", 1 },
101 { "r10", 10 },
102 { "r11", 11 },
103 { "r12", 12 },
104 { "r13", 13 },
105 { "r14", 14 },
106 { "r15", 15 },
107 { "r16", 16 },
108 { "r17", 17 },
109 { "r18", 18 },
110 { "r19", 19 },
111 { "r2", 2 },
112 { "r20", 20 },
113 { "r21", 21 },
114 { "r22", 22 },
115 { "r23", 23 },
116 { "r24", 24 },
117 { "r25", 25 },
118 { "r26", 26 },
119 { "r27", 27 },
120 { "r28", 28 },
121 { "r29", 29 },
122 { "r3", 3 },
123 { "r30", 30 },
124 { "r31", 31 },
125 { "r4", 4 },
126 { "r5", 5 },
127 { "r6", 6 },
128 { "r7", 7 },
129 { "r8", 8 },
130 { "r9", 9 },
131 { "sp", 3 }, /* sp - stack ptr */
132 { "tp", 5 }, /* tp - text ptr */
133 { "zero", 0 },
134};
135#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct reg_name))
136
137
138static const struct reg_name system_registers[] =
139{
140 { "eipc", 0 },
141 { "eipsw", 1 },
142 { "fepc", 2 },
143 { "fepsw", 3 },
144 { "ecr", 4 },
145 { "psw", 5 },
146};
147#define SYSREG_NAME_CNT (sizeof(system_registers) / sizeof(struct reg_name))
148
149static const struct reg_name cc_names[] =
150{
151 { "c", 0x1 },
152 { "ge", 0xe },
153 { "gt", 0xf },
154 { "h", 0xb },
155 { "l", 0x1 },
156 { "le", 0x7 },
157 { "lt", 0x6 },
158 { "n", 0x4 },
159 { "nc", 0x9 },
160 { "nh", 0x3 },
161 { "nl", 0x9 },
162 { "ns", 0xc },
163 { "nv", 0x8 },
164 { "nz", 0xa },
165 { "p", 0xc },
166 { "s", 0x4 },
167 { "sa", 0xd },
168 { "t", 0x5 },
169 { "v", 0x0 },
170 { "z", 0x2 },
171};
172#define CC_NAME_CNT (sizeof(cc_names) / sizeof(struct reg_name))
173
174/* reg_name_search does a binary search of the given register table
175 to see if "name" is a valid regiter name. Returns the register
176 number from the array on success, or -1 on failure. */
177
178static int
179reg_name_search (regs, regcount, name)
180 const struct reg_name *regs;
181 int regcount;
182 const char *name;
183{
184 int middle, low, high;
185 int cmp;
186
187 low = 0;
188 high = regcount - 1;
189
190 do
191 {
192 middle = (low + high) / 2;
193 cmp = strcasecmp (name, regs[middle].name);
194 if (cmp < 0)
195 high = middle - 1;
196 else if (cmp > 0)
197 low = middle + 1;
198 else
199 return regs[middle].value;
200 }
201 while (low <= high);
202 return -1;
203}
204
205
206/* Summary of register_name().
207 *
208 * in: Input_line_pointer points to 1st char of operand.
209 *
210 * out: A expressionS.
211 * The operand may have been a register: in this case, X_op == O_register,
212 * X_add_number is set to the register number, and truth is returned.
213 * Input_line_pointer->(next non-blank) char after operand, or is in
214 * its original state.
215 */
216static boolean
217register_name (expressionP)
218 expressionS *expressionP;
219{
220 int reg_number;
221 char *name;
222 char *start;
223 char c;
224
225 /* Find the spelling of the operand */
226 start = name = input_line_pointer;
227
228 c = get_symbol_end ();
229 reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
230
231 /* look to see if it's in the register table */
232 if (reg_number >= 0)
233 {
234 expressionP->X_op = O_register;
235 expressionP->X_add_number = reg_number;
236
237 /* make the rest nice */
238 expressionP->X_add_symbol = NULL;
239 expressionP->X_op_symbol = NULL;
240 *input_line_pointer = c; /* put back the delimiting char */
241 return true;
242 }
243 else
244 {
245 /* reset the line as if we had not done anything */
246 *input_line_pointer = c; /* put back the delimiting char */
247 input_line_pointer = start; /* reset input_line pointer */
248 return false;
249 }
250}
251
252/* Summary of system_register_name().
253 *
254 * in: Input_line_pointer points to 1st char of operand.
255 *
256 * out: A expressionS.
257 * The operand may have been a register: in this case, X_op == O_register,
258 * X_add_number is set to the register number, and truth is returned.
259 * Input_line_pointer->(next non-blank) char after operand, or is in
260 * its original state.
261 */
262static boolean
263system_register_name (expressionP)
264 expressionS *expressionP;
265{
266 int reg_number;
267 char *name;
268 char *start;
269 char c;
270
271 /* Find the spelling of the operand */
272 start = name = input_line_pointer;
273
274 c = get_symbol_end ();
275 reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
276
277 /* look to see if it's in the register table */
278 if (reg_number >= 0)
279 {
280 expressionP->X_op = O_register;
281 expressionP->X_add_number = reg_number;
282
283 /* make the rest nice */
284 expressionP->X_add_symbol = NULL;
285 expressionP->X_op_symbol = NULL;
286 *input_line_pointer = c; /* put back the delimiting char */
287 return true;
288 }
289 else
290 {
291 /* reset the line as if we had not done anything */
292 *input_line_pointer = c; /* put back the delimiting char */
293 input_line_pointer = start; /* reset input_line pointer */
294 return false;
295 }
296}
297
298/* Summary of cc_name().
299 *
300 * in: Input_line_pointer points to 1st char of operand.
301 *
302 * out: A expressionS.
303 * The operand may have been a register: in this case, X_op == O_register,
304 * X_add_number is set to the register number, and truth is returned.
305 * Input_line_pointer->(next non-blank) char after operand, or is in
306 * its original state.
307 */
308static boolean
309cc_name (expressionP)
310 expressionS *expressionP;
311{
312 int reg_number;
313 char *name;
314 char *start;
315 char c;
316
317 /* Find the spelling of the operand */
318 start = name = input_line_pointer;
319
320 c = get_symbol_end ();
321 reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
322
323 /* look to see if it's in the register table */
324 if (reg_number >= 0)
325 {
326 expressionP->X_op = O_constant;
327 expressionP->X_add_number = reg_number;
328
329 /* make the rest nice */
330 expressionP->X_add_symbol = NULL;
331 expressionP->X_op_symbol = NULL;
332 *input_line_pointer = c; /* put back the delimiting char */
333 return true;
334 }
335 else
336 {
337 /* reset the line as if we had not done anything */
338 *input_line_pointer = c; /* put back the delimiting char */
339 input_line_pointer = start; /* reset input_line pointer */
340 return false;
341 }
342}
343
344void
345md_show_usage (stream)
346 FILE *stream;
347{
ae1b99e4 348 fprintf(stream, "MN10300 options:\n\
0f91d763
JL
349none yet\n");
350}
351
352int
353md_parse_option (c, arg)
354 int c;
355 char *arg;
356{
357 return 0;
358}
359
360symbolS *
361md_undefined_symbol (name)
362 char *name;
363{
364 return 0;
365}
366
367char *
368md_atof (type, litp, sizep)
369 int type;
370 char *litp;
371 int *sizep;
372{
373 int prec;
374 LITTLENUM_TYPE words[4];
375 char *t;
376 int i;
377
378 switch (type)
379 {
380 case 'f':
381 prec = 2;
382 break;
383
384 case 'd':
385 prec = 4;
386 break;
387
388 default:
389 *sizep = 0;
390 return "bad call to md_atof";
391 }
392
393 t = atof_ieee (input_line_pointer, type, words);
394 if (t)
395 input_line_pointer = t;
396
397 *sizep = prec * 2;
398
399 for (i = prec - 1; i >= 0; i--)
400 {
401 md_number_to_chars (litp, (valueT) words[i], 2);
402 litp += 2;
403 }
404
405 return NULL;
406}
407
408
409void
410md_convert_frag (abfd, sec, fragP)
411 bfd *abfd;
412 asection *sec;
413 fragS *fragP;
414{
415 /* printf ("call to md_convert_frag \n"); */
416 abort ();
417}
418
419valueT
420md_section_align (seg, addr)
421 asection *seg;
422 valueT addr;
423{
424 int align = bfd_get_section_alignment (stdoutput, seg);
425 return ((addr + (1 << align) - 1) & (-1 << align));
426}
427
428void
429md_begin ()
430{
431 char *prev_name = "";
ae1b99e4 432 register const struct mn10300_opcode *op;
0f91d763 433
ae1b99e4 434 mn10300_hash = hash_new();
0f91d763 435
ae1b99e4 436 /* Insert unique names into hash table. The MN10300 instruction set
0f91d763
JL
437 has many identical opcode names that have different opcodes based
438 on the operands. This hash table then provides a quick index to
439 the first opcode with a particular name in the opcode table. */
440
ae1b99e4 441 op = mn10300_opcodes;
0f91d763
JL
442 while (op->name)
443 {
444 if (strcmp (prev_name, op->name))
445 {
446 prev_name = (char *) op->name;
ae1b99e4 447 hash_insert (mn10300_hash, op->name, (char *) op);
0f91d763
JL
448 }
449 op++;
450 }
451}
452
453static bfd_reloc_code_real_type
ae1b99e4 454mn10300_reloc_prefix()
0f91d763
JL
455{
456 if (strncmp(input_line_pointer, "hi0(", 4) == 0)
457 {
458 input_line_pointer += 4;
459 return BFD_RELOC_HI16;
460 }
461 if (strncmp(input_line_pointer, "hi(", 3) == 0)
462 {
463 input_line_pointer += 3;
464 return BFD_RELOC_HI16_S;
465 }
466 if (strncmp (input_line_pointer, "lo(", 3) == 0)
467 {
468 input_line_pointer += 3;
469 return BFD_RELOC_LO16;
470 }
471
472 /* FIXME: implement sda, tda, zda here */
473
474 return BFD_RELOC_UNUSED;
475}
476
477void
478md_assemble (str)
479 char *str;
480{
481 char *s;
ae1b99e4
JL
482 struct mn10300_opcode *opcode;
483 struct mn10300_opcode *next_opcode;
0f91d763
JL
484 const unsigned char *opindex_ptr;
485 int next_opindex;
486 unsigned long insn, size;
487 char *f;
488 int i;
489 int match;
490 bfd_reloc_code_real_type reloc;
491
492 /* Get the opcode. */
493 for (s = str; *s != '\0' && ! isspace (*s); s++)
494 ;
495 if (*s != '\0')
496 *s++ = '\0';
497
498 /* find the first opcode with the proper name */
ae1b99e4 499 opcode = (struct mn10300_opcode *)hash_find (mn10300_hash, str);
0f91d763
JL
500 if (opcode == NULL)
501 {
502 as_bad ("Unrecognized opcode: `%s'", str);
503 return;
504 }
505
506 str = s;
507 while (isspace (*str))
508 ++str;
509
510 input_line_pointer = str;
511
512 for(;;)
513 {
514 const char *errmsg = NULL;
515
516 fc = 0;
517 match = 0;
518 next_opindex = 0;
519 insn = opcode->opcode;
520 for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
521 {
ae1b99e4 522 const struct mn10300_operand *operand;
0f91d763
JL
523 char *hold;
524 expressionS ex;
525
526 if (next_opindex == 0)
527 {
ae1b99e4 528 operand = &mn10300_operands[*opindex_ptr];
0f91d763
JL
529 }
530 else
531 {
ae1b99e4 532 operand = &mn10300_operands[next_opindex];
0f91d763
JL
533 next_opindex = 0;
534 }
535
536 errmsg = NULL;
537
538 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
539 ++str;
540
541 /* Gather the operand. */
542 hold = input_line_pointer;
543 input_line_pointer = str;
544
545
546 /* lo(), hi(), hi0(), etc... */
ae1b99e4 547 if ((reloc = mn10300_reloc_prefix()) != BFD_RELOC_UNUSED)
0f91d763
JL
548 {
549 expression(&ex);
550
551 if (*input_line_pointer++ != ')')
552 {
553 errmsg = "syntax error: expected `)'";
554 goto error;
555 }
556
557 if (ex.X_op == O_constant)
558 {
559 switch (reloc)
560 {
561 case BFD_RELOC_LO16:
562 ex.X_add_number &= 0xffff;
563 break;
564
565 case BFD_RELOC_HI16:
566 ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff);
567 break;
568
569 case BFD_RELOC_HI16_S:
570 ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)
571 + ((ex.X_add_number >> 15) & 1);
572 break;
573
574 default:
575 break;
576 }
577
ae1b99e4 578 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
579 (char *) NULL, 0);
580 }
581 else
582 {
583 if (fc > MAX_INSN_FIXUPS)
584 as_fatal ("too many fixups");
585
586 fixups[fc].exp = ex;
587 fixups[fc].opindex = *opindex_ptr;
588 fixups[fc].reloc = reloc;
589 fc++;
590 }
591 }
592 else
593 {
594 switch (ex.X_op)
595 {
596 case O_illegal:
597 errmsg = "illegal operand";
598 goto error;
599 case O_absent:
600 errmsg = "missing operand";
601 goto error;
602 case O_register:
603
ae1b99e4 604 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
605 (char *) NULL, 0);
606 break;
607
608 case O_constant:
ae1b99e4 609 insn = mn10300_insert_operand (insn, operand, ex.X_add_number,
0f91d763
JL
610 (char *) NULL, 0);
611 break;
612
613 default:
614 /* We need to generate a fixup for this expression. */
615 if (fc >= MAX_INSN_FIXUPS)
616 as_fatal ("too many fixups");
617 fixups[fc].exp = ex;
618 fixups[fc].opindex = *opindex_ptr;
619 fixups[fc].reloc = BFD_RELOC_UNUSED;
620 ++fc;
621 break;
622 }
623
624 }
625
626 str = input_line_pointer;
627 input_line_pointer = hold;
628
629 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
630 ++str;
631 }
632 match = 1;
633
634 error:
635 if (match == 0)
636 {
637 next_opcode = opcode + 1;
638 if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
639 {
640 opcode = next_opcode;
641 continue;
642 }
643
644 as_bad ("%s", errmsg);
645 return;
646 }
647 break;
648 }
649
650 while (isspace (*str))
651 ++str;
652
653 if (*str != '\0')
654 as_bad ("junk at end of line: `%s'", str);
655
656 input_line_pointer = str;
657
658 /* Write out the instruction.
659
660 Four byte insns have an opcode with the two high bits on. */
661 if ((insn & 0x0600) == 0x0600)
662 size = 4;
663 else
664 size = 2;
665 f = frag_more (size);
666 md_number_to_chars (f, insn, size);
667
668 /* Create any fixups. At this point we do not use a
669 bfd_reloc_code_real_type, but instead just use the
670 BFD_RELOC_UNUSED plus the operand index. This lets us easily
671 handle fixups for any operand type, although that is admittedly
672 not a very exciting feature. We pick a BFD reloc type in
673 md_apply_fix. */
674 for (i = 0; i < fc; i++)
675 {
ae1b99e4 676 const struct mn10300_operand *operand;
0f91d763 677
ae1b99e4 678 operand = &mn10300_operands[fixups[i].opindex];
0f91d763
JL
679 if (fixups[i].reloc != BFD_RELOC_UNUSED)
680 {
681 reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
682 int size;
683 int offset;
684 fixS *fixP;
685
686 if (!reloc_howto)
687 abort();
688
689 size = bfd_get_reloc_size (reloc_howto);
690 offset = 4 - size;
691
692 if (size < 1 || size > 4)
693 abort();
694
695 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
696 &fixups[i].exp,
697 reloc_howto->pc_relative,
698 fixups[i].reloc);
699 }
700 else
701 {
702 fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
703 &fixups[i].exp,
ae1b99e4 704 1 /* FIXME: MN10300_OPERAND_RELATIVE ??? */,
0f91d763
JL
705 ((bfd_reloc_code_real_type)
706 (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
707 }
708 }
709}
710
711
712/* if while processing a fixup, a reloc really needs to be created */
713/* then it is done here */
714
715arelent *
716tc_gen_reloc (seg, fixp)
717 asection *seg;
718 fixS *fixp;
719{
720 arelent *reloc;
721 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
722 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
723 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
724 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
725 if (reloc->howto == (reloc_howto_type *) NULL)
726 {
727 as_bad_where (fixp->fx_file, fixp->fx_line,
728 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
729 return NULL;
730 }
731 reloc->addend = fixp->fx_addnumber;
732 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
733 return reloc;
734}
735
736int
737md_estimate_size_before_relax (fragp, seg)
738 fragS *fragp;
739 asection *seg;
740{
741 return 0;
742}
743
744long
745md_pcrel_from (fixp)
746 fixS *fixp;
747{
748 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
749 {
750 /* The symbol is undefined. Let the linker figure it out. */
751 return 0;
752 }
753 return fixp->fx_frag->fr_address + fixp->fx_where;
754}
755
756int
757md_apply_fix3 (fixp, valuep, seg)
758 fixS *fixp;
759 valueT *valuep;
760 segT seg;
761{
762 valueT value;
763 char *where;
764
765 if (fixp->fx_addsy == (symbolS *) NULL)
766 {
767 value = *valuep;
768 fixp->fx_done = 1;
769 }
770 else if (fixp->fx_pcrel)
771 value = *valuep;
772 else
773 {
774 value = fixp->fx_offset;
775 if (fixp->fx_subsy != (symbolS *) NULL)
776 {
777 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
778 value -= S_GET_VALUE (fixp->fx_subsy);
779 else
780 {
781 /* We don't actually support subtracting a symbol. */
782 as_bad_where (fixp->fx_file, fixp->fx_line,
783 "expression too complex");
784 }
785 }
786 }
787
788 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
789
790 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
791 {
792 int opindex;
ae1b99e4 793 const struct mn10300_operand *operand;
0f91d763
JL
794 char *where;
795 unsigned long insn;
796
797 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
ae1b99e4 798 operand = &mn10300_operands[opindex];
0f91d763
JL
799
800 /* Fetch the instruction, insert the fully resolved operand
801 value, and stuff the instruction back again.
802
803 Note the instruction has been stored in little endian
804 format! */
805 where = fixp->fx_frag->fr_literal + fixp->fx_where;
806
807 insn = bfd_getl32((unsigned char *) where);
ae1b99e4 808 insn = mn10300_insert_operand (insn, operand, (offsetT) value,
0f91d763
JL
809 fixp->fx_file, fixp->fx_line);
810 bfd_putl32((bfd_vma) insn, (unsigned char *) where);
811
812 if (fixp->fx_done)
813 {
814 /* Nothing else to do here. */
815 return 1;
816 }
817
818 /* Determine a BFD reloc value based on the operand information.
819 We are only prepared to turn a few of the operands into relocs. */
820
821 {
822 as_bad_where(fixp->fx_file, fixp->fx_line,
823 "unresolved expression that must be resolved");
824 fixp->fx_done = 1;
825 return 1;
826 }
827 }
828 else if (fixp->fx_done)
829 {
830 /* We still have to insert the value into memory! */
831 where = fixp->fx_frag->fr_literal + fixp->fx_where;
832 if (fixp->fx_size == 1)
833 *where = value & 0xff;
834 if (fixp->fx_size == 2)
835 bfd_putl16(value & 0xffff, (unsigned char *) where);
836 if (fixp->fx_size == 4)
837 bfd_putl32(value, (unsigned char *) where);
838 }
839
840 fixp->fx_addnumber = value;
841 return 1;
842}
843
844\f
845/* Insert an operand value into an instruction. */
846
847static unsigned long
ae1b99e4 848mn10300_insert_operand (insn, operand, val, file, line)
0f91d763 849 unsigned long insn;
ae1b99e4 850 const struct mn10300_operand *operand;
0f91d763
JL
851 offsetT val;
852 char *file;
853 unsigned int line;
854{
855 if (operand->bits != 16)
856 {
857 long min, max;
858 offsetT test;
859
860 {
861 max = (1 << operand->bits) - 1;
862 min = 0;
863 }
864
865 test = val;
866
867
868 if (test < (offsetT) min || test > (offsetT) max)
869 {
870 const char *err =
871 "operand out of range (%s not between %ld and %ld)";
872 char buf[100];
873
874 sprint_value (buf, test);
875 if (file == (char *) NULL)
876 as_warn (err, buf, min, max);
877 else
878 as_warn_where (file, line, err, buf, min, max);
879 }
880 }
881
882 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
883 return insn;
884}
This page took 0.063475 seconds and 4 git commands to generate.