* config/tc-v850.c (md_convert_frag): Don't set fragP->fr_fix
[deliverable/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"
10fba7f1
JL
27
28/* Temporarily holds the reloc in a cons expression. */
29static bfd_reloc_code_real_type hold_cons_reloc;
c6aa56bc 30\f
0e8f9bd1
JL
31/* Structure to hold information about predefined registers. */
32struct reg_name
33{
34 const char *name;
35 int value;
36};
37
c6aa56bc
C
38/* Generic assembler global variables which must be defined by all targets. */
39
40/* Characters which always start a comment. */
41const char comment_chars[] = "#";
42
43/* Characters which start a comment at the beginning of a line. */
dcf5d117 44const char line_comment_chars[] = ";#";
c6aa56bc
C
45
46/* Characters which may be used to separate multiple commands on a
47 single line. */
48const char line_separator_chars[] = ";";
49
50/* Characters which are used to indicate an exponent in a floating
51 point number. */
52const char EXP_CHARS[] = "eE";
53
54/* Characters which mean that a number is a floating point constant,
55 as in 0d1.0. */
56const char FLT_CHARS[] = "dD";
57\f
f964b01d 58
a334533c
JL
59const relax_typeS md_relax_table[] = {
60 {0xff, -0x100, 2, 1},
61 {0x1fffff, -0x200000, 6, 0},
62};
63
c6aa56bc
C
64/* local functions */
65static unsigned long v850_insert_operand
66 PARAMS ((unsigned long insn, const struct v850_operand *operand,
67 offsetT val, char *file, unsigned int line));
c84615bc 68static int reg_name_search PARAMS ((const struct reg_name *, int, const char *));
c6aa56bc 69static boolean register_name PARAMS ((expressionS *expressionP));
0e8f9bd1 70static boolean system_register_name PARAMS ((expressionS *expressionP));
c9f1b2d9 71static boolean cc_name PARAMS ((expressionS *expressionP));
f964b01d 72static bfd_reloc_code_real_type v850_reloc_prefix PARAMS ((void));
c6aa56bc
C
73
74
75/* fixups */
76#define MAX_INSN_FIXUPS (5)
77struct v850_fixup
78{
79 expressionS exp;
80 int opindex;
81 bfd_reloc_code_real_type reloc;
82};
83struct v850_fixup fixups[MAX_INSN_FIXUPS];
84static int fc;
85\f
86const char *md_shortopts = "";
87struct option md_longopts[] = {
88 {NULL, no_argument, NULL, 0}
89};
90size_t md_longopts_size = sizeof(md_longopts);
91
92/* The target specific pseudo-ops which we support. */
93const pseudo_typeS md_pseudo_table[] =
94{
7e96935e 95 {"word", cons, 4},
c6aa56bc
C
96 { NULL, NULL, 0 }
97};
98
99/* Opcode hash table. */
100static struct hash_control *v850_hash;
101
1510cd39
C
102/* This table is sorted. Suitable for searching by a binary search. */
103static const struct reg_name pre_defined_registers[] =
c6aa56bc
C
104{
105 { "ep", 30 }, /* ep - element ptr */
106 { "gp", 4 }, /* gp - global ptr */
107 { "lp", 31 }, /* lp - link ptr */
108 { "r0", 0 },
109 { "r1", 1 },
110 { "r10", 10 },
111 { "r11", 11 },
112 { "r12", 12 },
113 { "r13", 13 },
114 { "r14", 14 },
115 { "r15", 15 },
116 { "r16", 16 },
117 { "r17", 17 },
118 { "r18", 18 },
119 { "r19", 19 },
120 { "r2", 2 },
121 { "r20", 20 },
122 { "r21", 21 },
123 { "r22", 22 },
124 { "r23", 23 },
125 { "r24", 24 },
126 { "r25", 25 },
127 { "r26", 26 },
128 { "r27", 27 },
129 { "r28", 28 },
130 { "r29", 29 },
131 { "r3", 3 },
132 { "r30", 30 },
133 { "r31", 31 },
134 { "r4", 4 },
135 { "r5", 5 },
136 { "r6", 6 },
137 { "r7", 7 },
138 { "r8", 8 },
139 { "r9", 9 },
140 { "sp", 3 }, /* sp - stack ptr */
141 { "tp", 5 }, /* tp - text ptr */
142 { "zero", 0 },
143};
1510cd39
C
144#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct reg_name))
145
146
147static const struct reg_name system_registers[] =
148{
149 { "eipc", 0 },
150 { "eipsw", 1 },
151 { "fepc", 2 },
152 { "fepsw", 3 },
153 { "ecr", 4 },
154 { "psw", 5 },
155};
0e8f9bd1 156#define SYSREG_NAME_CNT (sizeof(system_registers) / sizeof(struct reg_name))
1510cd39
C
157
158static const struct reg_name cc_names[] =
159{
160 { "c", 0x1 },
161 { "ge", 0xe },
162 { "gt", 0xf },
163 { "h", 0xb },
164 { "l", 0x1 },
165 { "le", 0x7 },
166 { "lt", 0x6 },
167 { "n", 0x4 },
168 { "nc", 0x9 },
169 { "nh", 0x3 },
170 { "nl", 0x9 },
171 { "ns", 0xc },
172 { "nv", 0x8 },
173 { "nz", 0xa },
174 { "p", 0xc },
175 { "s", 0x4 },
176 { "sa", 0xd },
177 { "t", 0x5 },
178 { "v", 0x0 },
179 { "z", 0x2 },
180};
c9f1b2d9 181#define CC_NAME_CNT (sizeof(cc_names) / sizeof(struct reg_name))
c6aa56bc 182
0e8f9bd1
JL
183/* reg_name_search does a binary search of the given register table
184 to see if "name" is a valid regiter name. Returns the register
c6aa56bc
C
185 number from the array on success, or -1 on failure. */
186
187static int
c84615bc
C
188reg_name_search (regs, regcount, name)
189 const struct reg_name *regs;
190 int regcount;
191 const char *name;
c6aa56bc 192{
c84615bc 193 int middle, low, high;
c6aa56bc
C
194 int cmp;
195
196 low = 0;
c84615bc
C
197 high = regcount - 1;
198
c6aa56bc
C
199 do
200 {
201 middle = (low + high) / 2;
c84615bc 202 cmp = strcasecmp (name, regs[middle].name);
c6aa56bc
C
203 if (cmp < 0)
204 high = middle - 1;
205 else if (cmp > 0)
206 low = middle + 1;
207 else
c84615bc 208 return regs[middle].value;
c6aa56bc
C
209 }
210 while (low <= high);
211 return -1;
212}
213
214
215/* Summary of register_name().
216 *
217 * in: Input_line_pointer points to 1st char of operand.
218 *
219 * out: A expressionS.
220 * The operand may have been a register: in this case, X_op == O_register,
221 * X_add_number is set to the register number, and truth is returned.
222 * Input_line_pointer->(next non-blank) char after operand, or is in
223 * its original state.
224 */
225static boolean
226register_name (expressionP)
227 expressionS *expressionP;
228{
229 int reg_number;
230 char *name;
231 char *start;
232 char c;
233
234 /* Find the spelling of the operand */
235 start = name = input_line_pointer;
236
237 c = get_symbol_end ();
c84615bc 238 reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name);
0e8f9bd1
JL
239
240 /* look to see if it's in the register table */
241 if (reg_number >= 0)
242 {
243 expressionP->X_op = O_register;
244 expressionP->X_add_number = reg_number;
245
246 /* make the rest nice */
247 expressionP->X_add_symbol = NULL;
248 expressionP->X_op_symbol = NULL;
249 *input_line_pointer = c; /* put back the delimiting char */
250 return true;
251 }
252 else
253 {
254 /* reset the line as if we had not done anything */
255 *input_line_pointer = c; /* put back the delimiting char */
256 input_line_pointer = start; /* reset input_line pointer */
257 return false;
258 }
259}
260
261/* Summary of system_register_name().
262 *
263 * in: Input_line_pointer points to 1st char of operand.
264 *
265 * out: A expressionS.
266 * The operand may have been a register: in this case, X_op == O_register,
267 * X_add_number is set to the register number, and truth is returned.
268 * Input_line_pointer->(next non-blank) char after operand, or is in
269 * its original state.
270 */
271static boolean
272system_register_name (expressionP)
273 expressionS *expressionP;
274{
275 int reg_number;
276 char *name;
277 char *start;
278 char c;
279
280 /* Find the spelling of the operand */
281 start = name = input_line_pointer;
282
283 c = get_symbol_end ();
c84615bc 284 reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name);
c6aa56bc
C
285
286 /* look to see if it's in the register table */
287 if (reg_number >= 0)
288 {
289 expressionP->X_op = O_register;
290 expressionP->X_add_number = reg_number;
291
292 /* make the rest nice */
293 expressionP->X_add_symbol = NULL;
294 expressionP->X_op_symbol = NULL;
295 *input_line_pointer = c; /* put back the delimiting char */
296 return true;
297 }
298 else
299 {
300 /* reset the line as if we had not done anything */
301 *input_line_pointer = c; /* put back the delimiting char */
302 input_line_pointer = start; /* reset input_line pointer */
303 return false;
304 }
305}
306
c9f1b2d9
JL
307/* Summary of cc_name().
308 *
309 * in: Input_line_pointer points to 1st char of operand.
310 *
311 * out: A expressionS.
312 * The operand may have been a register: in this case, X_op == O_register,
313 * X_add_number is set to the register number, and truth is returned.
314 * Input_line_pointer->(next non-blank) char after operand, or is in
315 * its original state.
316 */
317static boolean
318cc_name (expressionP)
319 expressionS *expressionP;
320{
321 int reg_number;
322 char *name;
323 char *start;
324 char c;
325
326 /* Find the spelling of the operand */
327 start = name = input_line_pointer;
328
329 c = get_symbol_end ();
c84615bc 330 reg_number = reg_name_search (cc_names, CC_NAME_CNT, name);
c9f1b2d9
JL
331
332 /* look to see if it's in the register table */
333 if (reg_number >= 0)
334 {
335 expressionP->X_op = O_constant;
336 expressionP->X_add_number = reg_number;
337
338 /* make the rest nice */
339 expressionP->X_add_symbol = NULL;
340 expressionP->X_op_symbol = NULL;
341 *input_line_pointer = c; /* put back the delimiting char */
342 return true;
343 }
344 else
345 {
346 /* reset the line as if we had not done anything */
347 *input_line_pointer = c; /* put back the delimiting char */
348 input_line_pointer = start; /* reset input_line pointer */
349 return false;
350 }
351}
352
c6aa56bc
C
353void
354md_show_usage (stream)
355 FILE *stream;
356{
357 fprintf(stream, "V850 options:\n\
358none yet\n");
359}
360
361int
362md_parse_option (c, arg)
363 int c;
364 char *arg;
365{
366 return 0;
367}
368
369symbolS *
370md_undefined_symbol (name)
371 char *name;
372{
373 return 0;
374}
375
376char *
377md_atof (type, litp, sizep)
378 int type;
379 char *litp;
380 int *sizep;
381{
382 int prec;
383 LITTLENUM_TYPE words[4];
384 char *t;
385 int i;
386
387 switch (type)
388 {
389 case 'f':
390 prec = 2;
391 break;
392
393 case 'd':
394 prec = 4;
395 break;
396
397 default:
398 *sizep = 0;
399 return "bad call to md_atof";
400 }
401
402 t = atof_ieee (input_line_pointer, type, words);
403 if (t)
404 input_line_pointer = t;
405
406 *sizep = prec * 2;
407
408 for (i = prec - 1; i >= 0; i--)
409 {
410 md_number_to_chars (litp, (valueT) words[i], 2);
411 litp += 2;
412 }
413
414 return NULL;
415}
416
417
a334533c 418/* Very gross. */
c6aa56bc
C
419void
420md_convert_frag (abfd, sec, fragP)
421 bfd *abfd;
422 asection *sec;
423 fragS *fragP;
424{
a334533c
JL
425 subseg_change (sec, 0);
426 if (fragP->fr_subtype == 0)
427 {
428 fragP->fr_var = 0;
bc49fab8 429 fragP->fr_fix += 2;
a334533c
JL
430 fix_new (fragP, 0, 2, fragP->fr_symbol,
431 fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode);
432 }
433 else if (fragP->fr_subtype == 1)
434 {
435 fragP->fr_var = 0;
bc49fab8 436 fragP->fr_fix += 6;
a334533c
JL
437 /* Reverse the condition of the first branch. */
438 fragP->fr_literal[0] &= 0xf7;
439 /* Mask off all the displacement bits. */
440 fragP->fr_literal[0] &= 0x8f;
441 fragP->fr_literal[1] &= 0x07;
442 /* Now set the displacement bits so that we branch
443 around the unconditional branch. */
444 fragP->fr_literal[0] |= 0x30;
445
446 /* Now create the unconditional branch + fixup to the final
447 target. */
448 md_number_to_chars (&fragP->fr_literal[2], 0x00000780, 4);
449 fix_new (fragP, 2, 4, fragP->fr_symbol,
450 fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1);
451 }
452 else
453 abort ();
c6aa56bc
C
454}
455
456valueT
457md_section_align (seg, addr)
458 asection *seg;
459 valueT addr;
460{
461 int align = bfd_get_section_alignment (stdoutput, seg);
462 return ((addr + (1 << align) - 1) & (-1 << align));
463}
464
465void
466md_begin ()
467{
468 char *prev_name = "";
469 register const struct v850_opcode *op;
c6aa56bc
C
470
471 v850_hash = hash_new();
472
473 /* Insert unique names into hash table. The V850 instruction set
474 has many identical opcode names that have different opcodes based
475 on the operands. This hash table then provides a quick index to
476 the first opcode with a particular name in the opcode table. */
477
478 op = v850_opcodes;
05631de2 479 while (op->name)
c6aa56bc
C
480 {
481 if (strcmp (prev_name, op->name))
482 {
483 prev_name = (char *) op->name;
484 hash_insert (v850_hash, op->name, (char *) op);
485 }
05631de2 486 op++;
c6aa56bc
C
487 }
488}
489
c84615bc
C
490static bfd_reloc_code_real_type
491v850_reloc_prefix()
c6aa56bc 492{
c84615bc
C
493 if (strncmp(input_line_pointer, "hi0(", 4) == 0)
494 {
d3bbd9dc 495 input_line_pointer += 3;
c84615bc
C
496 return BFD_RELOC_HI16;
497 }
498 if (strncmp(input_line_pointer, "hi(", 3) == 0)
499 {
d3bbd9dc 500 input_line_pointer += 2;
c84615bc
C
501 return BFD_RELOC_HI16_S;
502 }
503 if (strncmp (input_line_pointer, "lo(", 3) == 0)
504 {
d3bbd9dc 505 input_line_pointer += 2;
c84615bc
C
506 return BFD_RELOC_LO16;
507 }
c6aa56bc 508
548ddc71
JL
509 if (strncmp (input_line_pointer, "sdaoff(", 7) == 0)
510 {
d3bbd9dc 511 input_line_pointer += 6;
548ddc71
JL
512 return BFD_RELOC_V850_SDA_OFFSET;
513 }
514
515 if (strncmp (input_line_pointer, "zdaoff(", 7) == 0)
516 {
d3bbd9dc 517 input_line_pointer += 6;
548ddc71
JL
518 return BFD_RELOC_V850_ZDA_OFFSET;
519 }
520
521 if (strncmp (input_line_pointer, "tdaoff(", 7) == 0)
522 {
d3bbd9dc 523 input_line_pointer += 6;
548ddc71
JL
524 return BFD_RELOC_V850_TDA_OFFSET;
525 }
526
d3bbd9dc
JL
527 /* Disgusting */
528 if (strncmp(input_line_pointer, "(hi0(", 5) == 0)
529 {
530 input_line_pointer += 4;
531 return BFD_RELOC_HI16;
532 }
533 if (strncmp(input_line_pointer, "(hi(", 4) == 0)
534 {
535 input_line_pointer += 3;
536 return BFD_RELOC_HI16_S;
537 }
538 if (strncmp (input_line_pointer, "(lo(", 4) == 0)
539 {
540 input_line_pointer += 3;
541 return BFD_RELOC_LO16;
542 }
543
544 if (strncmp (input_line_pointer, "(sdaoff(", 8) == 0)
545 {
546 input_line_pointer += 7;
547 return BFD_RELOC_V850_SDA_OFFSET;
548 }
549
550 if (strncmp (input_line_pointer, "(zdaoff(", 8) == 0)
551 {
552 input_line_pointer += 7;
553 return BFD_RELOC_V850_ZDA_OFFSET;
554 }
555
556 if (strncmp (input_line_pointer, "(tdaoff(", 8) == 0)
557 {
558 input_line_pointer += 7;
559 return BFD_RELOC_V850_TDA_OFFSET;
560 }
c84615bc
C
561
562 return BFD_RELOC_UNUSED;
563}
c6aa56bc 564
c6aa56bc
C
565void
566md_assemble (str)
567 char *str;
568{
569 char *s;
570 struct v850_opcode *opcode;
571 struct v850_opcode *next_opcode;
572 const unsigned char *opindex_ptr;
a334533c 573 int next_opindex, relaxable;
8ea15b86 574 unsigned long insn, insn_size;
c6aa56bc
C
575 char *f;
576 int i;
c6aa56bc 577 int match;
c84615bc 578 bfd_reloc_code_real_type reloc;
c6aa56bc 579
c6aa56bc
C
580 /* Get the opcode. */
581 for (s = str; *s != '\0' && ! isspace (*s); s++)
582 ;
583 if (*s != '\0')
584 *s++ = '\0';
585
586 /* find the first opcode with the proper name */
587 opcode = (struct v850_opcode *)hash_find (v850_hash, str);
588 if (opcode == NULL)
589 {
590 as_bad ("Unrecognized opcode: `%s'", str);
591 return;
592 }
593
594 str = s;
595 while (isspace (*str))
596 ++str;
597
598 input_line_pointer = str;
599
1510cd39 600 for(;;)
c6aa56bc 601 {
1510cd39
C
602 const char *errmsg = NULL;
603
a334533c 604 relaxable = 0;
1510cd39
C
605 fc = 0;
606 match = 0;
607 next_opindex = 0;
d5974c57 608 insn = opcode->opcode;
1510cd39 609 for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
c6aa56bc 610 {
1510cd39
C
611 const struct v850_operand *operand;
612 char *hold;
613 expressionS ex;
c6aa56bc 614
1510cd39 615 if (next_opindex == 0)
c6aa56bc 616 {
1510cd39
C
617 operand = &v850_operands[*opindex_ptr];
618 }
619 else
620 {
621 operand = &v850_operands[next_opindex];
622 next_opindex = 0;
c6aa56bc
C
623 }
624
1510cd39
C
625 errmsg = NULL;
626
627 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
628 ++str;
629
a334533c
JL
630 if (operand->flags & V850_OPERAND_RELAX)
631 relaxable = 1;
632
1510cd39
C
633 /* Gather the operand. */
634 hold = input_line_pointer;
635 input_line_pointer = str;
636
c84615bc
C
637
638 /* lo(), hi(), hi0(), etc... */
639 if ((reloc = v850_reloc_prefix()) != BFD_RELOC_UNUSED)
640 {
641 expression(&ex);
642
c84615bc
C
643 if (ex.X_op == O_constant)
644 {
645 switch (reloc)
646 {
647 case BFD_RELOC_LO16:
d3bbd9dc
JL
648 {
649 /* Truncate, then sign extend the value. */
650 int temp = ex.X_add_number & 0xffff;
651
652 /* XXX Assumes 32bit ints! */
653 temp = (temp << 16) >> 16;
654 ex.X_add_number = temp;
655 break;
656 }
c84615bc
C
657
658 case BFD_RELOC_HI16:
659 ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff);
660 break;
661
662 case BFD_RELOC_HI16_S:
663 ex.X_add_number = ((ex.X_add_number >> 16) & 0xffff)
664 + ((ex.X_add_number >> 15) & 1);
665 break;
f964b01d
JL
666
667 default:
668 break;
c84615bc
C
669 }
670
671 insn = v850_insert_operand (insn, operand, ex.X_add_number,
672 (char *) NULL, 0);
673 }
674 else
675 {
676 if (fc > MAX_INSN_FIXUPS)
677 as_fatal ("too many fixups");
678
679 fixups[fc].exp = ex;
680 fixups[fc].opindex = *opindex_ptr;
681 fixups[fc].reloc = reloc;
682 fc++;
683 }
684 }
685 else
686 {
a334533c 687 if ((operand->flags & V850_OPERAND_REG) != 0)
c6aa56bc 688 {
a334533c
JL
689 if (!register_name(&ex))
690 {
691 errmsg = "invalid register name";
692 goto error;
693 }
c6aa56bc 694 }
a334533c 695 else if ((operand->flags & V850_OPERAND_SRG) != 0)
0e8f9bd1 696 {
a334533c
JL
697 if (!system_register_name(&ex))
698 {
699 errmsg = "invalid system register name";
700 goto error;
701 }
0e8f9bd1 702 }
a334533c 703 else if ((operand->flags & V850_OPERAND_EP) != 0)
88b47a85 704 {
a334533c
JL
705 char *start = input_line_pointer;
706 char c = get_symbol_end ();
707 if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
708 {
709 /* Put things back the way we found them. */
710 *input_line_pointer = c;
711 input_line_pointer = start;
712 errmsg = "expected EP register";
713 goto error;
714 }
88b47a85 715 *input_line_pointer = c;
a334533c
JL
716 str = input_line_pointer;
717 input_line_pointer = hold;
718
719 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
720 ++str;
721 continue;
722 }
723 else if ((operand->flags & V850_OPERAND_CC) != 0)
724 {
725 if (!cc_name(&ex))
726 {
727 errmsg = "invalid condition code name";
728 goto error;
729 }
730 }
731 else if (register_name (&ex)
732 && (operand->flags & V850_OPERAND_REG) == 0)
733 {
734 errmsg = "syntax error: register not expected";
88b47a85
JL
735 goto error;
736 }
a334533c
JL
737 else if (system_register_name (&ex)
738 && (operand->flags & V850_OPERAND_SRG) == 0)
c9f1b2d9 739 {
a334533c 740 errmsg = "syntax error: system register not expected";
c9f1b2d9
JL
741 goto error;
742 }
a334533c
JL
743 else if (cc_name (&ex)
744 && (operand->flags & V850_OPERAND_CC) == 0)
1510cd39 745 {
a334533c 746 errmsg = "syntax error: condition code not expected";
1510cd39
C
747 goto error;
748 }
a334533c
JL
749 else
750 {
751 expression(&ex);
752 }
753
754 switch (ex.X_op)
755 {
756 case O_illegal:
757 errmsg = "illegal operand";
758 goto error;
759 case O_absent:
760 errmsg = "missing operand";
761 goto error;
762 case O_register:
763 if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
764 {
765 errmsg = "invalid operand";
766 goto error;
767 }
1510cd39 768
a334533c
JL
769 insn = v850_insert_operand (insn, operand, ex.X_add_number,
770 (char *) NULL, 0);
771 break;
772
773 case O_constant:
774 insn = v850_insert_operand (insn, operand, ex.X_add_number,
775 (char *) NULL, 0);
776 break;
777
778 default:
779 /* We need to generate a fixup for this expression. */
780 if (fc >= MAX_INSN_FIXUPS)
781 as_fatal ("too many fixups");
782 fixups[fc].exp = ex;
783 fixups[fc].opindex = *opindex_ptr;
784 fixups[fc].reloc = BFD_RELOC_UNUSED;
785 ++fc;
786 break;
787 }
1510cd39 788
c84615bc
C
789 }
790
791 str = input_line_pointer;
792 input_line_pointer = hold;
793
d3bbd9dc
JL
794 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']'
795 || *str == ')')
1510cd39
C
796 ++str;
797 }
798 match = 1;
799
800 error:
801 if (match == 0)
802 {
803 next_opcode = opcode + 1;
804 if (next_opcode->opcode != 0 && !strcmp(next_opcode->name, opcode->name))
805 {
806 opcode = next_opcode;
807 continue;
808 }
809
810 as_bad ("%s", errmsg);
811 return;
812 }
813 break;
814 }
815
c6aa56bc
C
816 while (isspace (*str))
817 ++str;
818
819 if (*str != '\0')
820 as_bad ("junk at end of line: `%s'", str);
1510cd39
C
821
822 input_line_pointer = str;
c6aa56bc 823
f964b01d 824 /* Write out the instruction.
c84615bc 825
f964b01d 826 Four byte insns have an opcode with the two high bits on. */
a334533c
JL
827 if (relaxable && fc > 0)
828 {
829 f = frag_var (rs_machine_dependent, 6, 4, 0,
830 fixups[0].exp.X_add_symbol, 0, (char *)fixups[0].opindex);
831 insn_size = 2;
832 md_number_to_chars (f, insn, insn_size);
833 md_number_to_chars (f + 2, 0, 4);
834 fc = 0;
835 }
836 else if ((insn & 0x0600) == 0x0600)
837 {
838 insn_size = 4;
839 f = frag_more (insn_size);
840 md_number_to_chars (f, insn, insn_size);
841 }
f964b01d 842 else
a334533c
JL
843 {
844 insn_size = 2;
845 f = frag_more (insn_size);
846 md_number_to_chars (f, insn, insn_size);
847 }
c84615bc
C
848
849 /* Create any fixups. At this point we do not use a
850 bfd_reloc_code_real_type, but instead just use the
851 BFD_RELOC_UNUSED plus the operand index. This lets us easily
852 handle fixups for any operand type, although that is admittedly
853 not a very exciting feature. We pick a BFD reloc type in
854 md_apply_fix. */
855 for (i = 0; i < fc; i++)
856 {
857 const struct v850_operand *operand;
858
859 operand = &v850_operands[fixups[i].opindex];
860 if (fixups[i].reloc != BFD_RELOC_UNUSED)
861 {
862 reloc_howto_type *reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc);
863 int size;
864 int offset;
865 fixS *fixP;
866
867 if (!reloc_howto)
868 abort();
869
870 size = bfd_get_reloc_size (reloc_howto);
8ea15b86
JL
871
872 /* The "size" of a TDA_OFFSET reloc varies depending
873 on what kind of instruction it's used in! */
874 if (reloc_howto->type == 11 && insn_size > 2)
875 size = 2;
c84615bc
C
876
877 if (size < 1 || size > 4)
878 abort();
879
8ea15b86 880 offset = 4 - size;
c84615bc
C
881 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size,
882 &fixups[i].exp,
883 reloc_howto->pc_relative,
884 fixups[i].reloc);
885 }
886 else
887 {
888 fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
889 &fixups[i].exp,
890 1 /* FIXME: V850_OPERAND_RELATIVE ??? */,
891 ((bfd_reloc_code_real_type)
892 (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
893 }
894 }
c6aa56bc
C
895}
896
897
898/* if while processing a fixup, a reloc really needs to be created */
899/* then it is done here */
900
901arelent *
902tc_gen_reloc (seg, fixp)
903 asection *seg;
904 fixS *fixp;
905{
906 arelent *reloc;
907 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
908 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
909 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
910 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
911 if (reloc->howto == (reloc_howto_type *) NULL)
912 {
913 as_bad_where (fixp->fx_file, fixp->fx_line,
914 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
915 return NULL;
916 }
917 reloc->addend = fixp->fx_addnumber;
918 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
919 return reloc;
920}
921
a334533c 922/* Assume everything will fit in two bytes, then expand as necessary. */
c6aa56bc
C
923int
924md_estimate_size_before_relax (fragp, seg)
925 fragS *fragp;
926 asection *seg;
927{
a334533c
JL
928 fragp->fr_var = 4;
929 return 2;
c6aa56bc
C
930}
931
a334533c 932
c6aa56bc 933long
0f8e50bb 934md_pcrel_from (fixp)
c6aa56bc 935 fixS *fixp;
c6aa56bc 936{
f964b01d
JL
937 /* If the symbol is undefined, or in a section other than our own,
938 then let the linker figure it out. */
0f8e50bb 939 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
c84615bc
C
940 {
941 /* The symbol is undefined. Let the linker figure it out. */
942 return 0;
943 }
944 return fixp->fx_frag->fr_address + fixp->fx_where;
c6aa56bc
C
945}
946
947int
948md_apply_fix3 (fixp, valuep, seg)
949 fixS *fixp;
950 valueT *valuep;
951 segT seg;
952{
c6aa56bc
C
953 valueT value;
954 char *where;
c6aa56bc
C
955
956 if (fixp->fx_addsy == (symbolS *) NULL)
957 {
958 value = *valuep;
959 fixp->fx_done = 1;
960 }
961 else if (fixp->fx_pcrel)
962 value = *valuep;
963 else
964 {
965 value = fixp->fx_offset;
966 if (fixp->fx_subsy != (symbolS *) NULL)
967 {
968 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
969 value -= S_GET_VALUE (fixp->fx_subsy);
970 else
971 {
972 /* We don't actually support subtracting a symbol. */
973 as_bad_where (fixp->fx_file, fixp->fx_line,
974 "expression too complex");
975 }
976 }
977 }
c6aa56bc 978
c84615bc 979 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
c6aa56bc 980
c84615bc
C
981 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
982 {
983 int opindex;
984 const struct v850_operand *operand;
985 char *where;
986 unsigned long insn;
987
988 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
989 operand = &v850_operands[opindex];
990
991 /* Fetch the instruction, insert the fully resolved operand
74dd0c07
JL
992 value, and stuff the instruction back again.
993
994 Note the instruction has been stored in little endian
995 format! */
c84615bc 996 where = fixp->fx_frag->fr_literal + fixp->fx_where;
74dd0c07
JL
997
998 insn = bfd_getl32((unsigned char *) where);
c84615bc
C
999 insn = v850_insert_operand (insn, operand, (offsetT) value,
1000 fixp->fx_file, fixp->fx_line);
74dd0c07 1001 bfd_putl32((bfd_vma) insn, (unsigned char *) where);
c84615bc
C
1002
1003 if (fixp->fx_done)
1004 {
1005 /* Nothing else to do here. */
1006 return 1;
1007 }
c6aa56bc 1008
c84615bc
C
1009 /* Determine a BFD reloc value based on the operand information.
1010 We are only prepared to turn a few of the operands into relocs. */
c6aa56bc 1011
c84615bc
C
1012 if (operand->bits == 22)
1013 fixp->fx_r_type = BFD_RELOC_V850_22_PCREL;
1014 else if (operand->bits == 9)
1015 fixp->fx_r_type = BFD_RELOC_V850_9_PCREL;
1016 else
1017 {
1018 as_bad_where(fixp->fx_file, fixp->fx_line,
1019 "unresolved expression that must be resolved");
1020 fixp->fx_done = 1;
1021 return 1;
1022 }
1023 }
2d56269e
JL
1024 else if (fixp->fx_done)
1025 {
1026 /* We still have to insert the value into memory! */
1027 where = fixp->fx_frag->fr_literal + fixp->fx_where;
1028 if (fixp->fx_size == 1)
1029 *where = value & 0xff;
1030 if (fixp->fx_size == 2)
1031 bfd_putl16(value & 0xffff, (unsigned char *) where);
1032 if (fixp->fx_size == 4)
1033 bfd_putl32(value, (unsigned char *) where);
1034 }
c6aa56bc
C
1035
1036 fixp->fx_addnumber = value;
1037 return 1;
c6aa56bc
C
1038}
1039
1040\f
1041/* Insert an operand value into an instruction. */
1042
1043static unsigned long
1044v850_insert_operand (insn, operand, val, file, line)
1045 unsigned long insn;
1046 const struct v850_operand *operand;
1047 offsetT val;
1048 char *file;
1049 unsigned int line;
1050{
c84615bc 1051 if (operand->bits != 16)
c6aa56bc
C
1052 {
1053 long min, max;
1054 offsetT test;
1055
1510cd39 1056 if ((operand->flags & V850_OPERAND_SIGNED) != 0)
c6aa56bc 1057 {
c6aa56bc
C
1058 max = (1 << (operand->bits - 1)) - 1;
1059 min = - (1 << (operand->bits - 1));
1060 }
1061 else
c6aa56bc
C
1062 {
1063 max = (1 << operand->bits) - 1;
1064 min = 0;
1065 }
1066
f964b01d 1067 test = val;
c6aa56bc
C
1068
1069
1070 if (test < (offsetT) min || test > (offsetT) max)
1071 {
1072 const char *err =
1073 "operand out of range (%s not between %ld and %ld)";
1074 char buf[100];
1075
1076 sprint_value (buf, test);
1077 if (file == (char *) NULL)
1078 as_warn (err, buf, min, max);
1079 else
1080 as_warn_where (file, line, err, buf, min, max);
1081 }
1082 }
1083
74dd0c07
JL
1084 if (operand->insert)
1085 {
1086 const char *message = NULL;
f964b01d 1087 insn = (*operand->insert) (insn, val, &message);
74dd0c07
JL
1088 if (message != NULL)
1089 {
1090 if (file == (char *) NULL)
1091 as_warn (message);
1092 else
1093 as_warn_where (file, line, message);
1094 }
1095 }
1096 else
1097 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
c6aa56bc
C
1098 return insn;
1099}
10fba7f1
JL
1100
1101/* Parse a cons expression. We have to handle hi(), lo(), etc
1102 on the v850. */
1103void
1104parse_cons_expression_v850 (exp)
1105 expressionS *exp;
1106{
1107 /* See if there's a reloc prefix like hi() we have to handle. */
1108 hold_cons_reloc = v850_reloc_prefix ();
1109
1110 /* Do normal expression parsing. */
1111 expression (exp);
10fba7f1
JL
1112}
1113
1114/* Create a fixup for a cons expression. If parse_cons_expression_v850
1115 found a reloc prefix, then we use that reloc, else we choose an
1116 appropriate one based on the size of the expression. */
1117void
1118cons_fix_new_v850 (frag, where, size, exp)
1119 fragS *frag;
1120 int where;
1121 int size;
1122 expressionS *exp;
1123{
1124 if (hold_cons_reloc == BFD_RELOC_UNUSED)
1125 {
1126 if (size == 4)
1127 hold_cons_reloc = BFD_RELOC_32;
1128 if (size == 2)
1129 hold_cons_reloc = BFD_RELOC_16;
1130 if (size == 1)
1131 hold_cons_reloc = BFD_RELOC_8;
1132 }
1133
1134 if (exp != NULL)
1135 fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc);
1136 else
1137 fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);
1138}
This page took 0.077171 seconds and 4 git commands to generate.