]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-v850.c
* write.c (fixup_segment): Don't add symbol value to addend if
[thirdparty/binutils-gdb.git] / gas / config / tc-v850.c
CommitLineData
c6aa56bc
C
1/* tc-v850.c -- Assembler code for the NEC V850
2
3 Copyright (C) 1996 Free Software Foundation.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include <stdio.h>
23#include <ctype.h>
24#include "as.h"
25#include "subsegs.h"
26#include "opcode/v850.h"
27\f
0e8f9bd1
JL
28/* Structure to hold information about predefined registers. */
29struct reg_name
30{
31 const char *name;
32 int value;
33};
34
c6aa56bc
C
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. */
dcf5d117 41const char line_comment_chars[] = ";#";
c6aa56bc
C
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
f964b01d 55
c6aa56bc
C
56/* local functions */
57static unsigned long v850_insert_operand
58 PARAMS ((unsigned long insn, const struct v850_operand *operand,
59 offsetT val, char *file, unsigned int line));
c84615bc 60static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
c6aa56bc 61static boolean register_name PARAMS ((expressionS *expressionP));
0e8f9bd1 62static boolean system_register_name PARAMS ((expressionS *expressionP));
c9f1b2d9 63static boolean cc_name PARAMS ((expressionS *expressionP));
f964b01d 64static bfd_reloc_code_real_type v850_reloc_prefix PARAMS ((void));
c6aa56bc
C
65
66
67/* fixups */
68#define MAX_INSN_FIXUPS (5)
69struct v850_fixup
70{
71 expressionS exp;
72 int opindex;
73 bfd_reloc_code_real_type reloc;
74};
75struct v850_fixup fixups[MAX_INSN_FIXUPS];
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{
c6aa56bc
C
87 { NULL, NULL, 0 }
88};
89
90/* Opcode hash table. */
91static struct hash_control *v850_hash;
92
1510cd39
C
93/* This table is sorted. Suitable for searching by a binary search. */
94static const struct reg_name pre_defined_registers[] =
c6aa56bc
C
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};
1510cd39
C
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};
0e8f9bd1 147#define SYSREG_NAME_CNT (sizeof(system_registers) / sizeof(struct reg_name))
1510cd39
C
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};
c9f1b2d9 172#define CC_NAME_CNT (sizeof(cc_names) / sizeof(struct reg_name))
c6aa56bc 173
0e8f9bd1
JL
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
c6aa56bc
C
176 number from the array on success, or -1 on failure. */
177
178static int
c84615bc
C
179reg_name_search (regs, regcount, name)
180 const struct reg_name *regs;
181 int regcount;
182 const char *name;
c6aa56bc 183{
c84615bc 184 int middle, low, high;
c6aa56bc
C
185 int cmp;
186
187 low = 0;
c84615bc
C
188 high = regcount - 1;
189
c6aa56bc
C
190 do
191 {
192 middle = (low + high) / 2;
c84615bc 193 cmp = strcasecmp (name, regs[middle].name);
c6aa56bc
C
194 if (cmp < 0)
195 high = middle - 1;
196 else if (cmp > 0)
197 low = middle + 1;
198 else
c84615bc 199 return regs[middle].value;
c6aa56bc
C
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 ();
c84615bc 229 reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
0e8f9bd1
JL
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 ();
c84615bc 275 reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
c6aa56bc
C
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
c9f1b2d9
JL
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 ();
c84615bc 321 reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
c9f1b2d9
JL
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
c6aa56bc
C
344void
345md_show_usage (stream)
346 FILE *stream;
347{
348 fprintf(stream, "V850 options:\n\
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 = "";
432 register const struct v850_opcode *op;
c6aa56bc
C
433
434 v850_hash = hash_new();
435
436 /* Insert unique names into hash table. The V850 instruction set
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
441 op = v850_opcodes;
05631de2 442 while (op->name)
c6aa56bc
C
443 {
444 if (strcmp (prev_name, op->name))
445 {
446 prev_name = (char *) op->name;
447 hash_insert (v850_hash, op->name, (char *) op);
448 }
05631de2 449 op++;
c6aa56bc
C
450 }
451}
452
c84615bc
C
453static bfd_reloc_code_real_type
454v850_reloc_prefix()
c6aa56bc 455{
c84615bc
C
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 }
c6aa56bc 471
c84615bc
C
472 /* FIXME: implement sda, tda, zda here */
473
474 return BFD_RELOC_UNUSED;
475}
c6aa56bc 476
c6aa56bc
C
477void
478md_assemble (str)
479 char *str;
480{
481 char *s;
482 struct v850_opcode *opcode;
483 struct v850_opcode *next_opcode;
484 const unsigned char *opindex_ptr;
485 int next_opindex;
f964b01d 486 unsigned long insn, size;
c6aa56bc
C
487 char *f;
488 int i;
c6aa56bc 489 int match;
c84615bc 490 bfd_reloc_code_real_type reloc;
c6aa56bc 491
c6aa56bc
C
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 */
499 opcode = (struct v850_opcode *)hash_find (v850_hash, str);
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
1510cd39 512 for(;;)
c6aa56bc 513 {
1510cd39
C
514 const char *errmsg = NULL;
515
516 fc = 0;
517 match = 0;
518 next_opindex = 0;
d5974c57 519 insn = opcode->opcode;
1510cd39 520 for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
c6aa56bc 521 {
1510cd39
C
522 const struct v850_operand *operand;
523 char *hold;
524 expressionS ex;
c6aa56bc 525
1510cd39 526 if (next_opindex == 0)
c6aa56bc 527 {
1510cd39
C
528 operand = &v850_operands[*opindex_ptr];
529 }
530 else
531 {
532 operand = &v850_operands[next_opindex];
533 next_opindex = 0;
c6aa56bc
C
534 }
535
1510cd39
C
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
c84615bc
C
545
546 /* lo(), hi(), hi0(), etc... */
547 if ((reloc = v850_reloc_prefix()) != BFD_RELOC_UNUSED)
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;
f964b01d
JL
573
574 default:
575 break;
c84615bc
C
576 }
577
578 insn = v850_insert_operand (insn, operand, ex.X_add_number,
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 {
1510cd39 594 if ((operand->flags & V850_OPERAND_REG) != 0)
c6aa56bc 595 {
1510cd39 596 if (!register_name(&ex))
c6aa56bc 597 {
1510cd39
C
598 errmsg = "invalid register name";
599 goto error;
c6aa56bc
C
600 }
601 }
0e8f9bd1
JL
602 else if ((operand->flags & V850_OPERAND_SRG) != 0)
603 {
604 if (!system_register_name(&ex))
605 {
606 errmsg = "invalid system register name";
607 goto error;
608 }
609 }
88b47a85
JL
610 else if ((operand->flags & V850_OPERAND_EP) != 0)
611 {
612 char *start = input_line_pointer;
613 char c = get_symbol_end ();
c84615bc 614 if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
88b47a85
JL
615 {
616 /* Put things back the way we found them. */
617 *input_line_pointer = c;
618 input_line_pointer = start;
619 errmsg = "expected EP register";
620 goto error;
621 }
622 *input_line_pointer = c;
623 str = input_line_pointer;
624 input_line_pointer = hold;
c84615bc 625
88b47a85
JL
626 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
627 ++str;
628 continue;
629 }
c9f1b2d9
JL
630 else if ((operand->flags & V850_OPERAND_CC) != 0)
631 {
632 if (!cc_name(&ex))
633 {
634 errmsg = "invalid condition code name";
635 goto error;
636 }
637 }
c9a32d6c
JL
638 else if (register_name (&ex)
639 && (operand->flags & V850_OPERAND_REG) == 0)
640 {
641 errmsg = "syntax error: register not expected";
642 goto error;
643 }
0e8f9bd1
JL
644 else if (system_register_name (&ex)
645 && (operand->flags & V850_OPERAND_SRG) == 0)
646 {
647 errmsg = "syntax error: system register not expected";
648 goto error;
649 }
c9f1b2d9
JL
650 else if (cc_name (&ex)
651 && (operand->flags & V850_OPERAND_CC) == 0)
652 {
653 errmsg = "syntax error: condition code not expected";
654 goto error;
655 }
1510cd39
C
656 else
657 {
c84615bc 658 expression(&ex);
1510cd39 659 }
c6aa56bc 660
1510cd39
C
661 switch (ex.X_op)
662 {
663 case O_illegal:
664 errmsg = "illegal operand";
665 goto error;
666 case O_absent:
667 errmsg = "missing operand";
668 goto error;
669 case O_register:
0e8f9bd1 670 if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
1510cd39
C
671 {
672 errmsg = "invalid operand";
673 goto error;
674 }
675
676 insn = v850_insert_operand (insn, operand, ex.X_add_number,
677 (char *) NULL, 0);
678 break;
679
680 case O_constant:
681 insn = v850_insert_operand (insn, operand, ex.X_add_number,
682 (char *) NULL, 0);
683 break;
684
685 default:
686 /* We need to generate a fixup for this expression. */
687 if (fc >= MAX_INSN_FIXUPS)
688 as_fatal ("too many fixups");
689 fixups[fc].exp = ex;
690 fixups[fc].opindex = *opindex_ptr;
691 fixups[fc].reloc = BFD_RELOC_UNUSED;
692 ++fc;
693 break;
694 }
695
c84615bc
C
696 }
697
698 str = input_line_pointer;
699 input_line_pointer = hold;
700
1510cd39
C
701 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
702 ++str;
703 }
704 match = 1;
705
706 error:
707 if (match == 0)
708 {
709 next_opcode = opcode + 1;
710 if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
711 {
712 opcode = next_opcode;
713 continue;
714 }
715
716 as_bad ("%s", errmsg);
717 return;
718 }
719 break;
720 }
721
c6aa56bc
C
722 while (isspace (*str))
723 ++str;
724
725 if (*str != '\0')
726 as_bad ("junk at end of line: `%s'", str);
1510cd39
C
727
728 input_line_pointer = str;
c6aa56bc 729
f964b01d 730 /* Write out the instruction.
c84615bc 731
f964b01d
JL
732 Four byte insns have an opcode with the two high bits on. */
733 if ((insn & 0x0600) == 0x0600)
734 size = 4;
735 else
736 size = 2;
737 f = frag_more (size);
738 md_number_to_chars (f, insn, size);
c84615bc
C
739
740 /* Create any fixups. At this point we do not use a
741 bfd_reloc_code_real_type, but instead just use the
742 BFD_RELOC_UNUSED plus the operand index. This lets us easily
743 handle fixups for any operand type, although that is admittedly
744 not a very exciting feature. We pick a BFD reloc type in
745 md_apply_fix. */
746 for (i = 0; i < fc; i++)
747 {
748 const struct v850_operand *operand;
749
750 operand = &v850_operands[fixups[i].opindex];
751 if (fixups[i].reloc != BFD_RELOC_UNUSED)
752 {
753 reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
754 int size;
755 int offset;
756 fixS *fixP;
757
758 if (!reloc_howto)
759 abort();
760
761 size = bfd_get_reloc_size (reloc_howto);
762 offset = 4 - size;
763
764 if (size < 1 || size > 4)
765 abort();
766
767 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
768 &fixups[i].exp,
769 reloc_howto->pc_relative,
770 fixups[i].reloc);
771 }
772 else
773 {
774 fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
775 &fixups[i].exp,
776 1 /* FIXME: V850_OPERAND_RELATIVE ??? */,
777 ((bfd_reloc_code_real_type)
778 (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
779 }
780 }
c6aa56bc
C
781}
782
783
784/* if while processing a fixup, a reloc really needs to be created */
785/* then it is done here */
786
787arelent *
788tc_gen_reloc (seg, fixp)
789 asection *seg;
790 fixS *fixp;
791{
792 arelent *reloc;
793 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
794 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
795 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
796 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
797 if (reloc->howto == (reloc_howto_type *) NULL)
798 {
799 as_bad_where (fixp->fx_file, fixp->fx_line,
800 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
801 return NULL;
802 }
803 reloc->addend = fixp->fx_addnumber;
804 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
805 return reloc;
806}
807
808int
809md_estimate_size_before_relax (fragp, seg)
810 fragS *fragp;
811 asection *seg;
812{
c6aa56bc
C
813 return 0;
814}
815
816long
0f8e50bb 817md_pcrel_from (fixp)
c6aa56bc 818 fixS *fixp;
c6aa56bc 819{
f964b01d
JL
820 /* If the symbol is undefined, or in a section other than our own,
821 then let the linker figure it out. */
0f8e50bb 822 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
c84615bc
C
823 {
824 /* The symbol is undefined. Let the linker figure it out. */
825 return 0;
826 }
827 return fixp->fx_frag->fr_address + fixp->fx_where;
c6aa56bc
C
828}
829
830int
831md_apply_fix3 (fixp, valuep, seg)
832 fixS *fixp;
833 valueT *valuep;
834 segT seg;
835{
c6aa56bc
C
836 valueT value;
837 char *where;
c6aa56bc
C
838
839 if (fixp->fx_addsy == (symbolS *) NULL)
840 {
841 value = *valuep;
842 fixp->fx_done = 1;
843 }
844 else if (fixp->fx_pcrel)
845 value = *valuep;
846 else
847 {
848 value = fixp->fx_offset;
849 if (fixp->fx_subsy != (symbolS *) NULL)
850 {
851 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
852 value -= S_GET_VALUE (fixp->fx_subsy);
853 else
854 {
855 /* We don't actually support subtracting a symbol. */
856 as_bad_where (fixp->fx_file, fixp->fx_line,
857 "expression too complex");
858 }
859 }
860 }
c6aa56bc 861
c84615bc 862 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
c6aa56bc 863
c84615bc
C
864 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
865 {
866 int opindex;
867 const struct v850_operand *operand;
868 char *where;
869 unsigned long insn;
870
871 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
872 operand = &v850_operands[opindex];
873
874 /* Fetch the instruction, insert the fully resolved operand
74dd0c07
JL
875 value, and stuff the instruction back again.
876
877 Note the instruction has been stored in little endian
878 format! */
c84615bc 879 where = fixp->fx_frag->fr_literal + fixp->fx_where;
74dd0c07
JL
880
881 insn = bfd_getl32((unsigned char *) where);
c84615bc
C
882 insn = v850_insert_operand (insn, operand, (offsetT) value,
883 fixp->fx_file, fixp->fx_line);
74dd0c07 884 bfd_putl32((bfd_vma) insn, (unsigned char *) where);
c84615bc
C
885
886 if (fixp->fx_done)
887 {
888 /* Nothing else to do here. */
889 return 1;
890 }
c6aa56bc 891
c84615bc
C
892 /* Determine a BFD reloc value based on the operand information.
893 We are only prepared to turn a few of the operands into relocs. */
c6aa56bc 894
c84615bc
C
895 if (operand->bits == 22)
896 fixp->fx_r_type = BFD_RELOC_V850_22_PCREL;
897 else if (operand->bits == 9)
898 fixp->fx_r_type = BFD_RELOC_V850_9_PCREL;
899 else
900 {
901 as_bad_where(fixp->fx_file, fixp->fx_line,
902 "unresolved expression that must be resolved");
903 fixp->fx_done = 1;
904 return 1;
905 }
906 }
2d56269e
JL
907 else if (fixp->fx_done)
908 {
909 /* We still have to insert the value into memory! */
910 where = fixp->fx_frag->fr_literal + fixp->fx_where;
911 if (fixp->fx_size == 1)
912 *where = value & 0xff;
913 if (fixp->fx_size == 2)
914 bfd_putl16(value & 0xffff, (unsigned char *) where);
915 if (fixp->fx_size == 4)
916 bfd_putl32(value, (unsigned char *) where);
917 }
c6aa56bc
C
918
919 fixp->fx_addnumber = value;
920 return 1;
c6aa56bc
C
921}
922
923\f
924/* Insert an operand value into an instruction. */
925
926static unsigned long
927v850_insert_operand (insn, operand, val, file, line)
928 unsigned long insn;
929 const struct v850_operand *operand;
930 offsetT val;
931 char *file;
932 unsigned int line;
933{
c84615bc 934 if (operand->bits != 16)
c6aa56bc
C
935 {
936 long min, max;
937 offsetT test;
938
1510cd39 939 if ((operand->flags & V850_OPERAND_SIGNED) != 0)
c6aa56bc 940 {
c6aa56bc
C
941 max = (1 << (operand->bits - 1)) - 1;
942 min = - (1 << (operand->bits - 1));
943 }
944 else
c6aa56bc
C
945 {
946 max = (1 << operand->bits) - 1;
947 min = 0;
948 }
949
f964b01d 950 test = val;
c6aa56bc
C
951
952
953 if (test < (offsetT) min || test > (offsetT) max)
954 {
955 const char *err =
956 "operand out of range (%s not between %ld and %ld)";
957 char buf[100];
958
959 sprint_value (buf, test);
960 if (file == (char *) NULL)
961 as_warn (err, buf, min, max);
962 else
963 as_warn_where (file, line, err, buf, min, max);
964 }
965 }
966
74dd0c07
JL
967 if (operand->insert)
968 {
969 const char *message = NULL;
f964b01d 970 insn = (*operand->insert) (insn, val, &message);
74dd0c07
JL
971 if (message != NULL)
972 {
973 if (file == (char *) NULL)
974 as_warn (message);
975 else
976 as_warn_where (file, line, message);
977 }
978 }
979 else
980 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
c6aa56bc
C
981 return insn;
982}