* config/tc-mn10300.c (md_assemble): Use FMT_* macros for
[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
778c521b
JL
667 /* Determine the size of the instruction. */
668 if (opcode->format == FMT_S0)
1217102f 669 size = 1;
0f91d763 670
778c521b 671 if (opcode->format == FMT_S1 || opcode->format == FMT_D0)
0f91d763 672 size = 2;
0f91d763 673
778c521b 674 if (opcode->format == FMT_S2 || opcode->format == FMT_D1)
1217102f 675 size = 3;
0f91d763 676
778c521b 677 if (opcode->format == FMT_S4)
1217102f 678 size = 5;
0f91d763 679
778c521b 680 if (opcode->format == FMT_S6 || opcode->format == FMT_D5)
1217102f 681 size = 7;
0f91d763 682
778c521b 683 if (opcode->format == FMT_D2)
1217102f 684 size = 4;
0f91d763 685
778c521b 686 if (opcode->format == FMT_D4)
1217102f
JL
687 size = 6;
688
1217102f
JL
689 /* Write out the instruction. */
690
691 f = frag_more (size);
1c3ae169 692 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
1217102f 693 if (size > 4)
1c3ae169 694 number_to_chars_bigendian (f + 4, 0, size - 4);
0f91d763
JL
695}
696
697
698/* if while processing a fixup, a reloc really needs to be created */
699/* then it is done here */
700
701arelent *
702tc_gen_reloc (seg, fixp)
703 asection *seg;
704 fixS *fixp;
705{
706 arelent *reloc;
707 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
708 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
709 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
710 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
711 if (reloc->howto == (reloc_howto_type *) NULL)
712 {
713 as_bad_where (fixp->fx_file, fixp->fx_line,
714 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
715 return NULL;
716 }
717 reloc->addend = fixp->fx_addnumber;
718 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
719 return reloc;
720}
721
722int
723md_estimate_size_before_relax (fragp, seg)
724 fragS *fragp;
725 asection *seg;
726{
727 return 0;
728}
729
730long
731md_pcrel_from (fixp)
732 fixS *fixp;
733{
734 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
735 {
736 /* The symbol is undefined. Let the linker figure it out. */
737 return 0;
738 }
739 return fixp->fx_frag->fr_address + fixp->fx_where;
740}
741
742int
743md_apply_fix3 (fixp, valuep, seg)
744 fixS *fixp;
745 valueT *valuep;
746 segT seg;
747{
748 valueT value;
749 char *where;
750
1217102f
JL
751 fixp->fx_done = 1;
752 return 0;
753
0f91d763
JL
754 if (fixp->fx_addsy == (symbolS *) NULL)
755 {
756 value = *valuep;
757 fixp->fx_done = 1;
758 }
759 else if (fixp->fx_pcrel)
760 value = *valuep;
761 else
762 {
763 value = fixp->fx_offset;
764 if (fixp->fx_subsy != (symbolS *) NULL)
765 {
766 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
767 value -= S_GET_VALUE (fixp->fx_subsy);
768 else
769 {
770 /* We don't actually support subtracting a symbol. */
771 as_bad_where (fixp->fx_file, fixp->fx_line,
772 "expression too complex");
773 }
774 }
775 }
776
777 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
778
779 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
780 {
781 int opindex;
ae1b99e4 782 const struct mn10300_operand *operand;
0f91d763
JL
783 char *where;
784 unsigned long insn;
785
786 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
ae1b99e4 787 operand = &mn10300_operands[opindex];
0f91d763
JL
788
789 /* Fetch the instruction, insert the fully resolved operand
790 value, and stuff the instruction back again.
791
792 Note the instruction has been stored in little endian
793 format! */
794 where = fixp->fx_frag->fr_literal + fixp->fx_where;
795
796 insn = bfd_getl32((unsigned char *) where);
ae1b99e4 797 insn = mn10300_insert_operand (insn, operand, (offsetT) value,
0f91d763
JL
798 fixp->fx_file, fixp->fx_line);
799 bfd_putl32((bfd_vma) insn, (unsigned char *) where);
800
801 if (fixp->fx_done)
802 {
803 /* Nothing else to do here. */
804 return 1;
805 }
806
807 /* Determine a BFD reloc value based on the operand information.
808 We are only prepared to turn a few of the operands into relocs. */
809
810 {
811 as_bad_where(fixp->fx_file, fixp->fx_line,
812 "unresolved expression that must be resolved");
813 fixp->fx_done = 1;
814 return 1;
815 }
816 }
817 else if (fixp->fx_done)
818 {
819 /* We still have to insert the value into memory! */
820 where = fixp->fx_frag->fr_literal + fixp->fx_where;
821 if (fixp->fx_size == 1)
822 *where = value & 0xff;
823 if (fixp->fx_size == 2)
824 bfd_putl16(value & 0xffff, (unsigned char *) where);
825 if (fixp->fx_size == 4)
826 bfd_putl32(value, (unsigned char *) where);
827 }
828
829 fixp->fx_addnumber = value;
830 return 1;
831}
832
0f91d763
JL
833/* Insert an operand value into an instruction. */
834
835static unsigned long
ae1b99e4 836mn10300_insert_operand (insn, operand, val, file, line)
0f91d763 837 unsigned long insn;
ae1b99e4 838 const struct mn10300_operand *operand;
0f91d763
JL
839 offsetT val;
840 char *file;
841 unsigned int line;
842{
1217102f 843 if (operand->bits != 32)
0f91d763
JL
844 {
845 long min, max;
846 offsetT test;
847
1217102f
JL
848 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
849 {
850 max = (1 << (operand->bits - 1)) - 1;
851 min = - (1 << (operand->bits - 1));
852 }
853 else
0f91d763
JL
854 {
855 max = (1 << operand->bits) - 1;
856 min = 0;
857 }
858
859 test = val;
860
861
862 if (test < (offsetT) min || test > (offsetT) max)
863 {
864 const char *err =
865 "operand out of range (%s not between %ld and %ld)";
866 char buf[100];
867
868 sprint_value (buf, test);
869 if (file == (char *) NULL)
870 as_warn (err, buf, min, max);
871 else
872 as_warn_where (file, line, err, buf, min, max);
873 }
874 }
875
876 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
877 return insn;
878}
1217102f
JL
879
880static unsigned long
881check_operand (insn, operand, val)
882 unsigned long insn;
883 const struct mn10300_operand *operand;
884 offsetT val;
885{
886 if (operand->bits != 32)
887 {
888 long min, max;
889 offsetT test;
890
891 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
892 {
893 max = (1 << (operand->bits - 1)) - 1;
894 min = - (1 << (operand->bits - 1));
895 }
896 else
897 {
898 max = (1 << operand->bits) - 1;
899 min = 0;
900 }
901
902 test = val;
903
904
905 if (test < (offsetT) min || test > (offsetT) max)
906 return 0;
907 else
908 return 1;
909 }
910 return 1;
911}
This page took 0.060847 seconds and 4 git commands to generate.