Brought up to date with respect to the branch
[deliverable/binutils-gdb.git] / gas / config / tc-v850.c
CommitLineData
c6aa56bc 1/* tc-v850.c -- Assembler code for the NEC V850
47bfb6fc 2 Copyright (C) 1996, 1997 Free Software Foundation.
c6aa56bc
C
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include <stdio.h>
22#include <ctype.h>
23#include "as.h"
24#include "subsegs.h"
25#include "opcode/v850.h"
10fba7f1 26
c2806093
NC
27#define AREA_ZDA 0
28#define AREA_SDA 1
29#define AREA_TDA 2
30
f483cb11
NC
31/* sign-extend a 16-bit number */
32#define SEXT16(x) ((((x) & 0xffff) ^ (~ 0x7fff)) + 0x8000)
33
10fba7f1
JL
34/* Temporarily holds the reloc in a cons expression. */
35static bfd_reloc_code_real_type hold_cons_reloc;
2d278484
NC
36
37/* Set to TRUE if we want to be pedantic about signed overflows. */
8816811b 38static boolean warn_signed_overflows = FALSE;
1fd5f4fc 39static boolean warn_unsigned_overflows = FALSE;
2d278484 40
d30a2be4 41/* Indicates the target BFD machine number. */
03c41a1c 42static int machine = -1;
8816811b 43
d30a2be4 44/* Indicates the target processor(s) for the assemble. */
03c41a1c 45static unsigned int processor_mask = -1;
d30a2be4 46
c6aa56bc 47\f
0e8f9bd1
JL
48/* Structure to hold information about predefined registers. */
49struct reg_name
50{
2d278484
NC
51 const char * name;
52 int value;
0e8f9bd1
JL
53};
54
c6aa56bc
C
55/* Generic assembler global variables which must be defined by all targets. */
56
57/* Characters which always start a comment. */
58const char comment_chars[] = "#";
59
60/* Characters which start a comment at the beginning of a line. */
f483cb11 61const char line_comment_chars[] = ";#";
c6aa56bc
C
62
63/* Characters which may be used to separate multiple commands on a
64 single line. */
65const char line_separator_chars[] = ";";
66
67/* Characters which are used to indicate an exponent in a floating
68 point number. */
69const char EXP_CHARS[] = "eE";
70
71/* Characters which mean that a number is a floating point constant,
72 as in 0d1.0. */
73const char FLT_CHARS[] = "dD";
74\f
f964b01d 75
c2806093
NC
76const relax_typeS md_relax_table[] =
77{
78 /* Conditional branches. */
79 {0xff, -0x100, 2, 1},
a334533c 80 {0x1fffff, -0x200000, 6, 0},
c2806093
NC
81 /* Unconditional branches. */
82 {0xff, -0x100, 2, 3},
83 {0x1fffff, -0x200000, 4, 0},
a334533c
JL
84};
85
035d8553 86
ccf10718
NC
87static segT sdata_section = NULL;
88static segT tdata_section = NULL;
89static segT zdata_section = NULL;
90static segT sbss_section = NULL;
91static segT tbss_section = NULL;
92static segT zbss_section = NULL;
93static segT rosdata_section = NULL;
94static segT rozdata_section = NULL;
c2806093
NC
95static segT scommon_section = NULL;
96static segT tcommon_section = NULL;
97static segT zcommon_section = NULL;
936a8f55
NC
98/* start-sanitize-v850e */
99static segT call_table_data_section = NULL;
100static segT call_table_text_section = NULL;
101/* end-sanitize-v850e */
ccf10718
NC
102
103
c6aa56bc
C
104/* local functions */
105static unsigned long v850_insert_operand
106 PARAMS ((unsigned long insn, const struct v850_operand *operand,
107 offsetT val, char *file, unsigned int line));
c6aa56bc
C
108
109
110/* fixups */
111#define MAX_INSN_FIXUPS (5)
112struct v850_fixup
113{
ccf10718
NC
114 expressionS exp;
115 int opindex;
c6aa56bc
C
116 bfd_reloc_code_real_type reloc;
117};
118struct v850_fixup fixups[MAX_INSN_FIXUPS];
119static int fc;
120\f
ccf10718
NC
121void
122v850_sdata (int ignore)
123{
c2806093 124 obj_elf_section_change_hook();
ccf10718 125
c2806093
NC
126 subseg_set (sdata_section, (subsegT) get_absolute_expression ());
127
ccf10718
NC
128 demand_empty_rest_of_line ();
129}
130
131void
132v850_tdata (int ignore)
133{
c2806093
NC
134 obj_elf_section_change_hook();
135
ccf10718
NC
136 subseg_set (tdata_section, (subsegT) get_absolute_expression ());
137
138 demand_empty_rest_of_line ();
139}
140
141void
142v850_zdata (int ignore)
143{
c2806093
NC
144 obj_elf_section_change_hook();
145
ccf10718
NC
146 subseg_set (zdata_section, (subsegT) get_absolute_expression ());
147
148 demand_empty_rest_of_line ();
149}
150
151void
152v850_sbss (int ignore)
153{
c2806093
NC
154 obj_elf_section_change_hook();
155
ccf10718
NC
156 subseg_set (sbss_section, (subsegT) get_absolute_expression ());
157
158 demand_empty_rest_of_line ();
159}
160
161void
162v850_tbss (int ignore)
163{
c2806093
NC
164 obj_elf_section_change_hook();
165
ccf10718
NC
166 subseg_set (tbss_section, (subsegT) get_absolute_expression ());
167
168 demand_empty_rest_of_line ();
169}
170
171void
172v850_zbss (int ignore)
173{
c2806093
NC
174 obj_elf_section_change_hook();
175
ccf10718
NC
176 subseg_set (zbss_section, (subsegT) get_absolute_expression ());
177
178 demand_empty_rest_of_line ();
179}
180
181void
182v850_rosdata (int ignore)
183{
c2806093
NC
184 obj_elf_section_change_hook();
185
ccf10718
NC
186 subseg_set (rosdata_section, (subsegT) get_absolute_expression ());
187
188 demand_empty_rest_of_line ();
189}
190
191void
192v850_rozdata (int ignore)
193{
c2806093
NC
194 obj_elf_section_change_hook();
195
ccf10718
NC
196 subseg_set (rozdata_section, (subsegT) get_absolute_expression ());
197
198 demand_empty_rest_of_line ();
199}
200
936a8f55
NC
201/* start-sanitize-v850e */
202void
203v850_call_table_data (int ignore)
204{
c2806093
NC
205 obj_elf_section_change_hook();
206
936a8f55
NC
207 subseg_set (call_table_data_section, (subsegT) get_absolute_expression ());
208
209 demand_empty_rest_of_line ();
210}
211
212void
213v850_call_table_text (int ignore)
214{
c2806093
NC
215 obj_elf_section_change_hook();
216
936a8f55
NC
217 subseg_set (call_table_text_section, (subsegT) get_absolute_expression ());
218
219 demand_empty_rest_of_line ();
220}
221/* end-sanitize-v850e */
222
19f40fdc
NC
223void
224v850_bss (int ignore)
225{
226 register int temp = get_absolute_expression ();
ccf10718
NC
227
228 obj_elf_section_change_hook();
19f40fdc
NC
229
230 subseg_set (bss_section, (subsegT) temp);
c2806093 231
19f40fdc
NC
232 demand_empty_rest_of_line ();
233}
234
235void
236v850_offset (int ignore)
237{
ccf10718
NC
238 int temp = get_absolute_expression ();
239
240 temp -= frag_now_fix();
19f40fdc 241
ccf10718
NC
242 if (temp > 0)
243 (void) frag_more (temp);
19f40fdc
NC
244
245 demand_empty_rest_of_line ();
246}
247
c2806093
NC
248/* Copied from obj_elf_common() in gas/config/obj-elf.c */
249static void
250v850_comm (area)
251 int area;
252{
253 char * name;
254 char c;
255 char * p;
256 int temp;
257 int size;
258 symbolS * symbolP;
259 int have_align;
260
261 name = input_line_pointer;
262 c = get_symbol_end ();
263 /* just after name is now '\0' */
264 p = input_line_pointer;
265 *p = c;
266 SKIP_WHITESPACE ();
267 if (*input_line_pointer != ',')
268 {
269 as_bad ("Expected comma after symbol-name");
270 ignore_rest_of_line ();
271 return;
272 }
273 input_line_pointer++; /* skip ',' */
274 if ((temp = get_absolute_expression ()) < 0)
275 {
276 as_bad (".COMMon length (%d.) <0! Ignored.", temp);
277 ignore_rest_of_line ();
278 return;
279 }
280 size = temp;
281 *p = 0;
282 symbolP = symbol_find_or_make (name);
283 *p = c;
284 if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
285 {
286 as_bad ("Ignoring attempt to re-define symbol");
287 ignore_rest_of_line ();
288 return;
289 }
290 if (S_GET_VALUE (symbolP) != 0)
291 {
292 if (S_GET_VALUE (symbolP) != size)
293 {
294 as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
295 S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
296 }
297 }
298 know (symbolP->sy_frag == &zero_address_frag);
299 if (*input_line_pointer != ',')
300 have_align = 0;
301 else
302 {
303 have_align = 1;
304 input_line_pointer++;
305 SKIP_WHITESPACE ();
306 }
307 if (! have_align || *input_line_pointer != '"')
308 {
309 if (! have_align)
310 temp = 0;
311 else
312 {
313 temp = get_absolute_expression ();
314 if (temp < 0)
315 {
316 temp = 0;
317 as_warn ("Common alignment negative; 0 assumed");
318 }
319 }
320 if (symbolP->local)
321 {
322 segT old_sec;
323 int old_subsec;
324 char * pfrag;
325 int align;
326
327 /* allocate_bss: */
328 old_sec = now_seg;
329 old_subsec = now_subseg;
330 if (temp)
331 {
332 /* convert to a power of 2 alignment */
333 for (align = 0; (temp & 1) == 0; temp >>= 1, ++align);
334 if (temp != 1)
335 {
336 as_bad ("Common alignment not a power of 2");
337 ignore_rest_of_line ();
338 return;
339 }
340 }
341 else
342 align = 0;
343 switch (area)
344 {
345 case AREA_SDA:
346 record_alignment (sbss_section, align);
347 obj_elf_section_change_hook();
348 subseg_set (sbss_section, 0);
349 break;
350
351 case AREA_ZDA:
352 record_alignment (zbss_section, align);
353 obj_elf_section_change_hook();
354 subseg_set (zbss_section, 0);
355 break;
356
357 case AREA_TDA:
358 record_alignment (tbss_section, align);
359 obj_elf_section_change_hook();
360 subseg_set (tbss_section, 0);
361 break;
362
363 default:
364 abort();
365 }
366
367 if (align)
368 frag_align (align, 0, 0);
369
370 switch (area)
371 {
372 case AREA_SDA:
373 if (S_GET_SEGMENT (symbolP) == sbss_section)
374 symbolP->sy_frag->fr_symbol = 0;
375 break;
376
377 case AREA_ZDA:
378 if (S_GET_SEGMENT (symbolP) == zbss_section)
379 symbolP->sy_frag->fr_symbol = 0;
380 break;
381
382 case AREA_TDA:
383 if (S_GET_SEGMENT (symbolP) == tbss_section)
384 symbolP->sy_frag->fr_symbol = 0;
385 break;
386
387 default:
388 abort();
389 }
390
391 symbolP->sy_frag = frag_now;
392 pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
393 (offsetT) size, (char *) 0);
394 *pfrag = 0;
395 S_SET_SIZE (symbolP, size);
396
397 switch (area)
398 {
399 case AREA_SDA: S_SET_SEGMENT (symbolP, sbss_section); break;
400 case AREA_ZDA: S_SET_SEGMENT (symbolP, zbss_section); break;
401 case AREA_TDA: S_SET_SEGMENT (symbolP, tbss_section); break;
402 default:
403 abort();
404 }
405
406 S_CLEAR_EXTERNAL (symbolP);
407 obj_elf_section_change_hook();
408 subseg_set (old_sec, old_subsec);
409 }
410 else
411 {
412 allocate_common:
413 S_SET_VALUE (symbolP, (valueT) size);
414 S_SET_ALIGN (symbolP, temp);
415 S_SET_EXTERNAL (symbolP);
416
417 switch (area)
418 {
419 case AREA_SDA: S_SET_SEGMENT (symbolP, scommon_section); break;
420 case AREA_ZDA: S_SET_SEGMENT (symbolP, zcommon_section); break;
421 case AREA_TDA: S_SET_SEGMENT (symbolP, tcommon_section); break;
422 default:
423 abort();
424 }
425 }
426 }
427 else
428 {
429 input_line_pointer++;
430 /* @@ Some use the dot, some don't. Can we get some consistency?? */
431 if (*input_line_pointer == '.')
432 input_line_pointer++;
433 /* @@ Some say data, some say bss. */
434 if (strncmp (input_line_pointer, "bss\"", 4)
435 && strncmp (input_line_pointer, "data\"", 5))
436 {
437 while (*--input_line_pointer != '"')
438 ;
439 input_line_pointer--;
440 goto bad_common_segment;
441 }
442 while (*input_line_pointer++ != '"')
443 ;
444 goto allocate_common;
445 }
446
447 symbolP->bsym->flags |= BSF_OBJECT;
448
449 demand_empty_rest_of_line ();
450 return;
451
452 {
453 bad_common_segment:
454 p = input_line_pointer;
455 while (*p && *p != '\n')
456 p++;
457 c = *p;
458 *p = '\0';
459 as_bad ("bad .common segment %s", input_line_pointer + 1);
460 *p = c;
461 input_line_pointer = p;
462 ignore_rest_of_line ();
463 return;
464 }
465}
466
1ffec081
NC
467void
468set_machine (int number)
469{
470 machine = number;
471 bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
d30a2be4
NC
472
473 switch (machine)
474 {
475 case 0: processor_mask = PROCESSOR_V850; break;
476/* start-sanitize-v850e */
8f3c5ddb 477 case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break;
d30a2be4 478 case bfd_mach_v850eq: processor_mask = PROCESSOR_V850EQ; break;
8f3c5ddb 479/* end-sanitize-v850e */
d30a2be4 480 }
1ffec081
NC
481}
482
c6aa56bc
C
483/* The target specific pseudo-ops which we support. */
484const pseudo_typeS md_pseudo_table[] =
485{
ccf10718
NC
486 {"sdata", v850_sdata, 0},
487 {"tdata", v850_tdata, 0},
488 {"zdata", v850_zdata, 0},
489 {"sbss", v850_sbss, 0},
490 {"tbss", v850_tbss, 0},
491 {"zbss", v850_zbss, 0},
492 {"rosdata", v850_rosdata, 0},
493 {"rozdata", v850_rozdata, 0},
19f40fdc
NC
494 {"bss", v850_bss, 0},
495 {"offset", v850_offset, 0},
19f40fdc 496 {"word", cons, 4},
c2806093
NC
497 {"zcomm", v850_comm, AREA_ZDA},
498 {"scomm", v850_comm, AREA_SDA},
499 {"tcomm", v850_comm, AREA_TDA},
1ffec081
NC
500 {"v850", set_machine, 0},
501/* start-sanitize-v850e */
936a8f55
NC
502 {"call_table_data", v850_call_table_data, 0},
503 {"call_table_text", v850_call_table_text, 0},
504 {"v850e", set_machine, bfd_mach_v850e},
936a8f55 505 {"v850eq", set_machine, bfd_mach_v850eq},
8f3c5ddb 506/* end-sanitize-v850e */
19f40fdc 507 { NULL, NULL, 0}
c6aa56bc
C
508};
509
510/* Opcode hash table. */
511static struct hash_control *v850_hash;
512
1510cd39
C
513/* This table is sorted. Suitable for searching by a binary search. */
514static const struct reg_name pre_defined_registers[] =
c6aa56bc 515{
ccf10718
NC
516 { "ep", 30 }, /* ep - element ptr */
517 { "gp", 4 }, /* gp - global ptr */
518 { "hp", 2 }, /* hp - handler stack ptr */
519 { "lp", 31 }, /* lp - link ptr */
520 { "r0", 0 },
521 { "r1", 1 },
c6aa56bc
C
522 { "r10", 10 },
523 { "r11", 11 },
524 { "r12", 12 },
525 { "r13", 13 },
526 { "r14", 14 },
527 { "r15", 15 },
528 { "r16", 16 },
529 { "r17", 17 },
530 { "r18", 18 },
531 { "r19", 19 },
ccf10718 532 { "r2", 2 },
c6aa56bc
C
533 { "r20", 20 },
534 { "r21", 21 },
535 { "r22", 22 },
536 { "r23", 23 },
537 { "r24", 24 },
538 { "r25", 25 },
539 { "r26", 26 },
540 { "r27", 27 },
541 { "r28", 28 },
542 { "r29", 29 },
ccf10718 543 { "r3", 3 },
c6aa56bc
C
544 { "r30", 30 },
545 { "r31", 31 },
ccf10718
NC
546 { "r4", 4 },
547 { "r5", 5 },
548 { "r6", 6 },
549 { "r7", 7 },
550 { "r8", 8 },
551 { "r9", 9 },
552 { "sp", 3 }, /* sp - stack ptr */
553 { "tp", 5 }, /* tp - text ptr */
c6aa56bc
C
554 { "zero", 0 },
555};
19f40fdc 556#define REG_NAME_CNT (sizeof (pre_defined_registers) / sizeof (struct reg_name))
1510cd39
C
557
558
559static const struct reg_name system_registers[] =
560{
19f40fdc
NC
561/* start-sanitize-v850e */
562 { "ctbp", 20 },
563 { "ctpc", 16 },
564 { "ctpsw", 17 },
565 { "dbpc", 18 },
566 { "dbpsw", 19 },
567/* end-sanitize-v850e */
ccf10718
NC
568 { "ecr", 4 },
569 { "eipc", 0 },
570 { "eipsw", 1 },
571 { "fepc", 2 },
572 { "fepsw", 3 },
573 { "psw", 5 },
1510cd39 574};
19f40fdc 575#define SYSREG_NAME_CNT (sizeof (system_registers) / sizeof (struct reg_name))
1510cd39 576
d4b2cc56
NC
577/* start-sanitize-v850e */
578static const struct reg_name system_list_registers[] =
579{
580 {"PS", 5 },
581 {"SR", 0 + 1}
582};
583#define SYSREGLIST_NAME_CNT (sizeof (system_list_registers) / sizeof (struct reg_name))
584/* end-sanitize-v850e */
585
1510cd39
C
586static const struct reg_name cc_names[] =
587{
ccf10718
NC
588 { "c", 0x1 },
589 { "e", 0x2 },
1510cd39
C
590 { "ge", 0xe },
591 { "gt", 0xf },
ccf10718
NC
592 { "h", 0xb },
593 { "l", 0x1 },
1510cd39
C
594 { "le", 0x7 },
595 { "lt", 0x6 },
ccf10718 596 { "n", 0x4 },
1510cd39 597 { "nc", 0x9 },
5f044499 598 { "ne", 0xa },
1510cd39
C
599 { "nh", 0x3 },
600 { "nl", 0x9 },
601 { "ns", 0xc },
602 { "nv", 0x8 },
603 { "nz", 0xa },
604 { "p", 0xc },
ccf10718 605 { "s", 0x4 },
1510cd39 606 { "sa", 0xd },
ccf10718
NC
607 { "t", 0x5 },
608 { "v", 0x0 },
609 { "z", 0x2 },
1510cd39 610};
9153e643 611#define CC_NAME_CNT (sizeof (cc_names) / sizeof (struct reg_name))
c6aa56bc 612
0e8f9bd1
JL
613/* reg_name_search does a binary search of the given register table
614 to see if "name" is a valid regiter name. Returns the register
c6aa56bc
C
615 number from the array on success, or -1 on failure. */
616
617static int
d4b2cc56 618reg_name_search (regs, regcount, name, accept_numbers)
ccf10718
NC
619 const struct reg_name * regs;
620 int regcount;
621 const char * name;
d4b2cc56 622 boolean accept_numbers;
c6aa56bc 623{
c84615bc 624 int middle, low, high;
c6aa56bc 625 int cmp;
d4b2cc56 626 symbolS * symbolP;
c6aa56bc 627
d4b2cc56
NC
628 /* If the register name is a symbol, then evaluate it. */
629 if ((symbolP = symbol_find (name)) != NULL)
630 {
631 /* If the symbol is an alias for another name then use that.
632 If the symbol is an alias for a number, then return the number. */
633 if (symbolP->sy_value.X_op == O_symbol)
634 {
635 name = S_GET_NAME (symbolP->sy_value.X_add_symbol);
636 }
637 else if (accept_numbers)
638 {
639 int reg = S_GET_VALUE (symbolP);
640
641 if (reg >= 0 && reg <= 31)
642 return reg;
643 }
644 }
645
c6aa56bc 646 low = 0;
c84615bc
C
647 high = regcount - 1;
648
c6aa56bc
C
649 do
650 {
651 middle = (low + high) / 2;
c84615bc 652 cmp = strcasecmp (name, regs[middle].name);
c6aa56bc
C
653 if (cmp < 0)
654 high = middle - 1;
655 else if (cmp > 0)
656 low = middle + 1;
19f40fdc
NC
657 else
658 return regs[middle].value;
c6aa56bc
C
659 }
660 while (low <= high);
661 return -1;
662}
663
664
665/* Summary of register_name().
666 *
667 * in: Input_line_pointer points to 1st char of operand.
668 *
669 * out: A expressionS.
670 * The operand may have been a register: in this case, X_op == O_register,
671 * X_add_number is set to the register number, and truth is returned.
672 * Input_line_pointer->(next non-blank) char after operand, or is in
673 * its original state.
674 */
675static boolean
676register_name (expressionP)
ccf10718 677 expressionS * expressionP;
c6aa56bc 678{
ccf10718
NC
679 int reg_number;
680 char * name;
681 char * start;
682 char c;
c6aa56bc
C
683
684 /* Find the spelling of the operand */
685 start = name = input_line_pointer;
686
687 c = get_symbol_end ();
ccf10718 688
d4b2cc56 689 reg_number = reg_name_search (pre_defined_registers, REG_NAME_CNT, name, FALSE);
0e8f9bd1 690
5f044499
NC
691 * input_line_pointer = c; /* put back the delimiting char */
692
0e8f9bd1
JL
693 /* look to see if it's in the register table */
694 if (reg_number >= 0)
695 {
5f044499 696 expressionP->X_op = O_register;
0e8f9bd1
JL
697 expressionP->X_add_number = reg_number;
698
699 /* make the rest nice */
700 expressionP->X_add_symbol = NULL;
5f044499
NC
701 expressionP->X_op_symbol = NULL;
702
0e8f9bd1
JL
703 return true;
704 }
705 else
706 {
707 /* reset the line as if we had not done anything */
5f044499
NC
708 input_line_pointer = start;
709
0e8f9bd1
JL
710 return false;
711 }
712}
713
714/* Summary of system_register_name().
715 *
d4b2cc56
NC
716 * in: Input_line_pointer points to 1st char of operand.
717 * expressionP points to an expression structure to be filled in.
718 * accept_numbers is true iff numerical register names may be used.
719 * start-sanitize-v850e
720 * accept_list_names is true iff the special names PS and SR may be
721 * accepted.
722 * end-sanitize-v850eq
0e8f9bd1 723 *
d4b2cc56 724 * out: A expressionS structure in expressionP.
0e8f9bd1
JL
725 * The operand may have been a register: in this case, X_op == O_register,
726 * X_add_number is set to the register number, and truth is returned.
727 * Input_line_pointer->(next non-blank) char after operand, or is in
728 * its original state.
729 */
730static boolean
d4b2cc56
NC
731system_register_name (expressionP, accept_numbers
732 /* start-sanitize-v850e */
733 , accept_list_names
734 /* end-sanitize-v850e */
735 )
19f40fdc
NC
736 expressionS * expressionP;
737 boolean accept_numbers;
d4b2cc56
NC
738/* start-sanitize-v850e */
739 boolean accept_list_names;
740/* end-sanitize-v850e */
0e8f9bd1 741{
ccf10718
NC
742 int reg_number;
743 char * name;
744 char * start;
745 char c;
0e8f9bd1
JL
746
747 /* Find the spelling of the operand */
748 start = name = input_line_pointer;
749
750 c = get_symbol_end ();
d4b2cc56 751 reg_number = reg_name_search (system_registers, SYSREG_NAME_CNT, name, accept_numbers);
c6aa56bc 752
5f044499
NC
753 * input_line_pointer = c; /* put back the delimiting char */
754
19f40fdc
NC
755 if (reg_number < 0
756 && accept_numbers)
757 {
19f40fdc 758 input_line_pointer = start; /* reset input_line pointer */
5f044499
NC
759
760 if (isdigit (* input_line_pointer))
d4b2cc56
NC
761 {
762 reg_number = strtol (input_line_pointer, & input_line_pointer, 10);
19f40fdc 763
d4b2cc56
NC
764 /* Make sure that the register number is allowable. */
765 if ( reg_number < 0
766 || reg_number > 5
19f40fdc 767/* start-sanitize-v850e */
d4b2cc56
NC
768 && reg_number < 16
769 || reg_number > 20
19f40fdc 770/* end-sanitize-v850e */
d4b2cc56
NC
771 )
772 {
773 reg_number = -1;
774 }
775 }
776/* start-sanitize-v850e */
777 else if (accept_list_names)
19f40fdc 778 {
d4b2cc56
NC
779 c = get_symbol_end ();
780 reg_number = reg_name_search (system_list_registers, SYSREGLIST_NAME_CNT, name, FALSE);
781
782 * input_line_pointer = c; /* put back the delimiting char */
19f40fdc 783 }
d4b2cc56 784/* end-sanitize-v850e */
19f40fdc
NC
785 }
786
c6aa56bc
C
787 /* look to see if it's in the register table */
788 if (reg_number >= 0)
789 {
5f044499 790 expressionP->X_op = O_register;
c6aa56bc
C
791 expressionP->X_add_number = reg_number;
792
793 /* make the rest nice */
794 expressionP->X_add_symbol = NULL;
5f044499
NC
795 expressionP->X_op_symbol = NULL;
796
c6aa56bc
C
797 return true;
798 }
799 else
800 {
801 /* reset the line as if we had not done anything */
5f044499
NC
802 input_line_pointer = start;
803
c6aa56bc
C
804 return false;
805 }
806}
807
c9f1b2d9
JL
808/* Summary of cc_name().
809 *
810 * in: Input_line_pointer points to 1st char of operand.
811 *
812 * out: A expressionS.
813 * The operand may have been a register: in this case, X_op == O_register,
814 * X_add_number is set to the register number, and truth is returned.
815 * Input_line_pointer->(next non-blank) char after operand, or is in
816 * its original state.
817 */
818static boolean
819cc_name (expressionP)
936a8f55 820 expressionS * expressionP;
c9f1b2d9 821{
ccf10718
NC
822 int reg_number;
823 char * name;
824 char * start;
825 char c;
c9f1b2d9
JL
826
827 /* Find the spelling of the operand */
828 start = name = input_line_pointer;
829
830 c = get_symbol_end ();
d4b2cc56 831 reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);
c9f1b2d9 832
5f044499
NC
833 * input_line_pointer = c; /* put back the delimiting char */
834
c9f1b2d9
JL
835 /* look to see if it's in the register table */
836 if (reg_number >= 0)
837 {
5f044499 838 expressionP->X_op = O_constant;
c9f1b2d9
JL
839 expressionP->X_add_number = reg_number;
840
841 /* make the rest nice */
842 expressionP->X_add_symbol = NULL;
5f044499
NC
843 expressionP->X_op_symbol = NULL;
844
c9f1b2d9
JL
845 return true;
846 }
847 else
848 {
849 /* reset the line as if we had not done anything */
5f044499
NC
850 input_line_pointer = start;
851
c9f1b2d9
JL
852 return false;
853 }
854}
855
5f044499
NC
856static void
857skip_white_space (void)
858{
859 while ( * input_line_pointer == ' '
860 || * input_line_pointer == '\t')
861 ++ input_line_pointer;
862}
863
035d8553
NC
864/* start-sanitize-v850e */
865/* Summary of parse_register_list ().
866 *
867 * in: Input_line_pointer points to 1st char of a list of registers.
868 * insn is the partially constructed instruction.
869 * operand is the operand being inserted.
870 *
c2806093
NC
871 * out: NULL if the parse completed successfully, otherwise a
872 * pointer to an error message is returned. If the parse
873 * completes the correct bit fields in the instruction
874 * will be filled in.
cf735d2a
NC
875 *
876 * Parses register lists with the syntax:
877 *
878 * { rX }
879 * { rX, rY }
880 * { rX - rY }
881 * { rX - rY, rZ }
882 * etc
883 *
884 * and also parses constant epxressions whoes bits indicate the
885 * registers in the lists. The LSB in the expression refers to
886 * the lowest numbered permissable register in the register list,
887 * and so on upwards. System registers are considered to be very
888 * high numbers.
889 *
035d8553 890 */
cf735d2a 891static char *
035d8553
NC
892parse_register_list
893(
894 unsigned long * insn,
895 const struct v850_operand * operand
896)
897{
898 static int type1_regs[ 32 ] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
035d8553
NC
899 static int type2_regs[ 32 ] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
900 static int type3_regs[ 32 ] = { 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 };
035d8553 901 int * regs;
cf735d2a
NC
902 expressionS exp;
903
035d8553
NC
904
905 /* Select a register array to parse. */
906 switch (operand->shift)
907 {
908 case 0xffe00001: regs = type1_regs; break;
035d8553
NC
909 case 0xfff8000f: regs = type2_regs; break;
910 case 0xfff8001f: regs = type3_regs; break;
035d8553 911 default:
5f044499 912 as_bad ("unknown operand shift: %x\n", operand->shift );
cf735d2a 913 return "internal failure in parse_register_list";
035d8553
NC
914 }
915
5f044499
NC
916 skip_white_space();
917
cf735d2a 918 /* If the expression starts with a curly brace it is a register list.
c2806093 919 Otherwise it is a constant expression, whoes bits indicate which
cf735d2a
NC
920 registers are to be included in the list. */
921
5f044499
NC
922 if (* input_line_pointer != '{')
923 {
cf735d2a
NC
924 int bits;
925 int reg;
926 int i;
927
928 expression (& exp);
929
930 if (exp.X_op != O_constant)
931 return "constant expression or register list expected";
932
cf735d2a 933 if (regs == type1_regs)
cf735d2a
NC
934 {
935 if (exp.X_add_number & 0xFFFFF000)
936 return "high bits set in register list expression";
937
938 for (reg = 20; reg < 32; reg ++)
939 if (exp.X_add_number & (1 << (reg - 20)))
940 {
941 for (i = 0; i < 32; i++)
942 if (regs[i] == reg)
943 * insn |= (1 << i);
944 }
945 }
cf735d2a
NC
946 else if (regs == type2_regs)
947 {
948 if (exp.X_add_number & 0xFFFE0000)
949 return "high bits set in register list expression";
950
951 for (reg = 1; reg < 16; reg ++)
952 if (exp.X_add_number & (1 << (reg - 1)))
953 {
954 for (i = 0; i < 32; i++)
955 if (regs[i] == reg)
956 * insn |= (1 << i);
957 }
958
959 if (exp.X_add_number & (1 << 15))
960 * insn |= (1 << 3);
961
962 if (exp.X_add_number & (1 << 16))
963 * insn |= (1 << 19);
964 }
965 else /* regs == type3_regs */
966 {
967 if (exp.X_add_number & 0xFFFE0000)
968 return "high bits set in register list expression";
969
970 for (reg = 16; reg < 32; reg ++)
971 if (exp.X_add_number & (1 << (reg - 16)))
972 {
973 for (i = 0; i < 32; i++)
974 if (regs[i] == reg)
975 * insn |= (1 << i);
976 }
977
978 if (exp.X_add_number & (1 << 16))
979 * insn |= (1 << 19);
980 }
cf735d2a
NC
981
982 return NULL;
5f044499
NC
983 }
984
985 input_line_pointer ++;
986
987 /* Parse the register list until a terminator (closing curly brace or new-line) is found. */
035d8553
NC
988 for (;;)
989 {
035d8553
NC
990 if (register_name (& exp))
991 {
5f044499
NC
992 int i;
993
035d8553
NC
994 /* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction. */
995 for (i = 0; i < 32; i++)
996 {
997 if (regs[ i ] == exp.X_add_number)
998 {
999 * insn |= (1 << i);
1000 break;
1001 }
1002 }
1003
1004 if (i == 32)
1005 {
cf735d2a 1006 return "illegal register included in list";
035d8553
NC
1007 }
1008 }
d4b2cc56 1009 else if (system_register_name (& exp, true, true))
035d8553
NC
1010 {
1011 if (regs == type1_regs)
1012 {
cf735d2a 1013 return "system registers cannot be included in list";
035d8553
NC
1014 }
1015 else if (exp.X_add_number == 5)
1016 {
1017 if (regs == type2_regs)
cf735d2a 1018 return "PSW cannot be included in list";
035d8553
NC
1019 else
1020 * insn |= 0x8;
1021 }
d4b2cc56 1022 else if (exp.X_add_number < 4)
035d8553 1023 * insn |= 0x80000;
d4b2cc56
NC
1024 else
1025 return "High value system registers cannot be included in list";
035d8553 1026 }
5f044499
NC
1027 else if (* input_line_pointer == '}')
1028 {
1029 input_line_pointer ++;
1030 break;
1031 }
1032 else if (* input_line_pointer == ',')
1033 {
1034 input_line_pointer ++;
1035 continue;
1036 }
1037 else if (* input_line_pointer == '-')
1038 {
1039 /* We have encountered a range of registers: rX - rY */
1040 int j;
1041 expressionS exp2;
1042
1043 /* Skip the dash. */
1044 ++ input_line_pointer;
1045
1046 /* Get the second register in the range. */
1047 if (! register_name (& exp2))
1048 {
cf735d2a 1049 return "second register should follow dash in register list";
5f044499
NC
1050 exp2.X_add_number = exp.X_add_number;
1051 }
1052
1053 /* Add the rest of the registers in the range. */
1054 for (j = exp.X_add_number + 1; j <= exp2.X_add_number; j++)
1055 {
1056 int i;
1057
1058 /* Locate the given register in the list, and if it is there, insert the corresponding bit into the instruction. */
1059 for (i = 0; i < 32; i++)
1060 {
1061 if (regs[ i ] == j)
1062 {
1063 * insn |= (1 << i);
1064 break;
1065 }
1066 }
1067
1068 if (i == 32)
1069 {
cf735d2a 1070 return "illegal register included in list";
5f044499
NC
1071 }
1072 }
1073 }
035d8553 1074 else
5f044499
NC
1075 {
1076 break;
1077 }
035d8553 1078
5f044499 1079 skip_white_space();
035d8553
NC
1080 }
1081
cf735d2a 1082 return NULL;
035d8553
NC
1083}
1084/* end-sanitize-v850e */
1085
1086CONST char * md_shortopts = "m:";
1087
1088struct option md_longopts[] =
1089{
1090 {NULL, no_argument, NULL, 0}
1091};
1092size_t md_longopts_size = sizeof md_longopts;
1093
1094
c6aa56bc
C
1095void
1096md_show_usage (stream)
936a8f55 1097 FILE * stream;
c6aa56bc 1098{
035d8553 1099 fprintf (stream, "V850 options:\n");
d4b2cc56
NC
1100 fprintf (stream, "\t-mwarn_signed_overflow Warn if signed immediate values overflow\n");
1101 fprintf (stream, "\t-mwarn_unsigned_overflow Warn if unsigned immediate values overflow\n");
1102 fprintf (stream, "\t-mv850 The code is targeted at the v850\n");
8816811b 1103/* start-sanitize-v850e */
d4b2cc56
NC
1104 fprintf (stream, "\t-mv850e The code is targeted at the v850e\n");
1105 fprintf (stream, "\t-mv850eq The code is targeted at the v850eq\n");
8f3c5ddb 1106/* end-sanitize-v850e */
c6aa56bc
C
1107}
1108
1109int
1110md_parse_option (c, arg)
035d8553
NC
1111 int c;
1112 char * arg;
c6aa56bc 1113{
d4b2cc56
NC
1114 if (c != 'm')
1115 return 0;
2d278484 1116
d4b2cc56
NC
1117 if (strcmp (arg, "warn_signed_overflow") == 0)
1118 {
1119 warn_signed_overflows = TRUE;
1120 }
1121 else if (strcmp (arg, "warn_unsigned_overflow") == 0)
1122 {
1123 warn_unsigned_overflows = TRUE;
1124 }
1125 else if (strcmp (arg, "v850") == 0)
1126 {
1127 machine = 0;
1128 processor_mask = PROCESSOR_V850;
1129 }
8816811b 1130/* start-sanitize-v850e */
d4b2cc56
NC
1131 else if (strcmp (arg, "v850e") == 0)
1132 {
1133 machine = bfd_mach_v850e;
1134 processor_mask = PROCESSOR_V850E;
1135 }
1136 else if (strcmp (arg, "v850eq") == 0)
1137 {
1138 machine = bfd_mach_v850eq;
1139 processor_mask = PROCESSOR_V850EQ;
1fd5f4fc 1140 }
d4b2cc56
NC
1141/* end-sanitize-v850e */
1142 else
1143 return 0;
8816811b 1144
d4b2cc56 1145 return 1;
c6aa56bc
C
1146}
1147
1148symbolS *
1149md_undefined_symbol (name)
ccf10718 1150 char * name;
c6aa56bc
C
1151{
1152 return 0;
1153}
1154
1155char *
1156md_atof (type, litp, sizep)
ccf10718
NC
1157 int type;
1158 char * litp;
1159 int * sizep;
c6aa56bc 1160{
ccf10718 1161 int prec;
c6aa56bc 1162 LITTLENUM_TYPE words[4];
ccf10718
NC
1163 char * t;
1164 int i;
c6aa56bc
C
1165
1166 switch (type)
1167 {
1168 case 'f':
1169 prec = 2;
1170 break;
1171
1172 case 'd':
1173 prec = 4;
1174 break;
1175
1176 default:
1177 *sizep = 0;
1178 return "bad call to md_atof";
1179 }
1180
1181 t = atof_ieee (input_line_pointer, type, words);
1182 if (t)
1183 input_line_pointer = t;
1184
1185 *sizep = prec * 2;
1186
1187 for (i = prec - 1; i >= 0; i--)
1188 {
1189 md_number_to_chars (litp, (valueT) words[i], 2);
1190 litp += 2;
1191 }
1192
1193 return NULL;
1194}
1195
1196
a334533c 1197/* Very gross. */
c6aa56bc
C
1198void
1199md_convert_frag (abfd, sec, fragP)
ccf10718
NC
1200 bfd * abfd;
1201 asection * sec;
1202 fragS * fragP;
c6aa56bc 1203{
a334533c 1204 subseg_change (sec, 0);
c2806093
NC
1205
1206 /* In range conditional or unconditional branch. */
1207 if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2)
a334533c 1208 {
2385d90a
JL
1209 fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
1210 fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode);
a334533c 1211 fragP->fr_var = 0;
bc49fab8 1212 fragP->fr_fix += 2;
a334533c 1213 }
c2806093 1214 /* Out of range conditional branch. Emit a branch around a jump. */
a334533c
JL
1215 else if (fragP->fr_subtype == 1)
1216 {
c2806093
NC
1217 unsigned char *buffer =
1218 (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
1219
a334533c 1220 /* Reverse the condition of the first branch. */
c2806093 1221 buffer[0] ^= 0x08;
a334533c 1222 /* Mask off all the displacement bits. */
c2806093
NC
1223 buffer[0] &= 0x8f;
1224 buffer[1] &= 0x07;
a334533c
JL
1225 /* Now set the displacement bits so that we branch
1226 around the unconditional branch. */
c2806093 1227 buffer[0] |= 0x30;
a334533c
JL
1228
1229 /* Now create the unconditional branch + fixup to the final
1230 target. */
c2806093 1231 md_number_to_chars (buffer + 2, 0x00000780, 4);
2385d90a 1232 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
a334533c 1233 fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1);
2385d90a
JL
1234 fragP->fr_var = 0;
1235 fragP->fr_fix += 6;
a334533c 1236 }
c2806093
NC
1237 /* Out of range unconditional branch. Emit a jump. */
1238 else if (fragP->fr_subtype == 3)
1239 {
1240 md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4);
1241 fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
1242 fragP->fr_offset, 1, BFD_RELOC_UNUSED + (int)fragP->fr_opcode + 1);
1243 fragP->fr_var = 0;
1244 fragP->fr_fix += 4;
1245 }
a334533c
JL
1246 else
1247 abort ();
c6aa56bc
C
1248}
1249
1250valueT
1251md_section_align (seg, addr)
ccf10718
NC
1252 asection * seg;
1253 valueT addr;
c6aa56bc
C
1254{
1255 int align = bfd_get_section_alignment (stdoutput, seg);
1256 return ((addr + (1 << align) - 1) & (-1 << align));
1257}
1258
1259void
1260md_begin ()
1261{
ccf10718
NC
1262 char * prev_name = "";
1263 register const struct v850_opcode * op;
1264 flagword applicable;
c6aa56bc 1265
8f3c5ddb 1266/* start-sanitize-v850e */
03c41a1c
NC
1267 if (strncmp (TARGET_CPU, "v850eq", 6) == 0)
1268 {
1269 if (machine == -1)
1270 machine = bfd_mach_v850eq;
1271
1272 if (processor_mask == -1)
1273 processor_mask = PROCESSOR_V850EQ;
1274 }
8f3c5ddb 1275 else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
03c41a1c
NC
1276 {
1277 if (machine == -1)
1278 machine = bfd_mach_v850e;
1279
1280 if (processor_mask == -1)
1281 processor_mask = PROCESSOR_V850E;
1282 }
1283 else
1284/* end-sanitize-v850e */
1285 if (strncmp (TARGET_CPU, "v850", 4) == 0)
1286 {
1287 if (machine == -1)
1288 machine = 0;
1289
1290 if (processor_mask == -1)
1291 processor_mask = PROCESSOR_V850;
1292 }
1293 else
1294 as_bad ("Unable to determine default target processor from string: %s",
1295 TARGET_CPU);
1296
c6aa56bc
C
1297 v850_hash = hash_new();
1298
1299 /* Insert unique names into hash table. The V850 instruction set
1300 has many identical opcode names that have different opcodes based
1301 on the operands. This hash table then provides a quick index to
1302 the first opcode with a particular name in the opcode table. */
1303
ccf10718 1304 op = v850_opcodes;
05631de2 1305 while (op->name)
c6aa56bc
C
1306 {
1307 if (strcmp (prev_name, op->name))
1308 {
1309 prev_name = (char *) op->name;
1310 hash_insert (v850_hash, op->name, (char *) op);
1311 }
05631de2 1312 op++;
c6aa56bc 1313 }
8816811b
NC
1314
1315 bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
ccf10718
NC
1316
1317 applicable = bfd_applicable_section_flags (stdoutput);
1318
1319 sdata_section = subseg_new (".sdata", 0);
1320 bfd_set_section_flags (stdoutput, sdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
1321
1322 tdata_section = subseg_new (".tdata", 0);
1323 bfd_set_section_flags (stdoutput, tdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
1324
1325 zdata_section = subseg_new (".zdata", 0);
1326 bfd_set_section_flags (stdoutput, zdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
1327
1328 sbss_section = subseg_new (".sbss", 0);
1329 bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC);
c2806093 1330 seg_info (sbss_section)->bss = 1;
ccf10718
NC
1331
1332 tbss_section = subseg_new (".tbss", 0);
1333 bfd_set_section_flags (stdoutput, tbss_section, applicable & SEC_ALLOC);
c2806093 1334 seg_info (tbss_section)->bss = 1;
ccf10718
NC
1335
1336 zbss_section = subseg_new (".zbss", 0);
1337 bfd_set_section_flags (stdoutput, zbss_section, applicable & SEC_ALLOC);
c2806093 1338 seg_info (zbss_section)->bss = 1;
ccf10718
NC
1339
1340 rosdata_section = subseg_new (".rosdata", 0);
1341 bfd_set_section_flags (stdoutput, rosdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY));
1342
1343 rozdata_section = subseg_new (".rozdata", 0);
1344 bfd_set_section_flags (stdoutput, rozdata_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_READONLY));
936a8f55 1345
c2806093
NC
1346 scommon_section = subseg_new (".scommon", 0);
1347 bfd_set_section_flags (stdoutput, scommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
1348
1349 zcommon_section = subseg_new (".zcommon", 0);
1350 bfd_set_section_flags (stdoutput, zcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
1351
d4b2cc56
NC
1352 tcommon_section = subseg_new (".tcommon", 0);
1353 bfd_set_section_flags (stdoutput, tcommon_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS | SEC_IS_COMMON));
1354
936a8f55
NC
1355/* start-sanitize-v850e */
1356 call_table_data_section = subseg_new (".call_table_data", 0);
1357 bfd_set_section_flags (stdoutput, call_table_data_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA | SEC_HAS_CONTENTS));
1358
1359 call_table_text_section = subseg_new (".call_table_text", 0);
1360 bfd_set_section_flags (stdoutput, call_table_text_section, applicable & (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE));
1361/* end-sanitize-v850e */
1362}
1363
1364
1365/* start-sanitize-v850e */
1366static bfd_reloc_code_real_type
1367handle_ctoff (const struct v850_operand * operand)
1368{
1369 if (operand == NULL)
1370 return BFD_RELOC_V850_CALLT_16_16_OFFSET;
1371
6df3c45f 1372 if ( operand->bits != 6
2b36e4c2 1373 || operand->shift != 0)
6df3c45f
NC
1374 {
1375 as_bad ("ctoff() relocation used on an instruction which does not support it");
1376 return BFD_RELOC_64; /* Used to indicate an error condition. */
1377 }
936a8f55
NC
1378
1379 return BFD_RELOC_V850_CALLT_6_7_OFFSET;
1380}
1381/* end-sanitize-v850e */
1382
1383static bfd_reloc_code_real_type
1384handle_sdaoff (const struct v850_operand * operand)
1385{
1386 if (operand == NULL) return BFD_RELOC_V850_SDA_16_16_OFFSET;
1387 if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_SDA_15_16_OFFSET;
1388 /* start-sanitize-v850e */
1389 if (operand->bits == -1) return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET;
1390 /* end-sanitize-v850e */
1391
6df3c45f 1392 if ( operand->bits != 16
2b36e4c2 1393 || operand->shift != 16)
6df3c45f
NC
1394 {
1395 as_bad ("sdaoff() relocation used on an instruction which does not support it");
1396 return BFD_RELOC_64; /* Used to indicate an error condition. */
1397 }
936a8f55
NC
1398
1399 return BFD_RELOC_V850_SDA_16_16_OFFSET;
1400}
1401
1402static bfd_reloc_code_real_type
1403handle_zdaoff (const struct v850_operand * operand)
1404{
1405 if (operand == NULL) return BFD_RELOC_V850_ZDA_16_16_OFFSET;
1406 if (operand->bits == 15 && operand->shift == 17) return BFD_RELOC_V850_ZDA_15_16_OFFSET;
1407 /* start-sanitize-v850e */
1408 if (operand->bits == -1) return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET;
1409 /* end-sanitize-v850e */
6df3c45f
NC
1410
1411 if ( operand->bits != 16
1412 || operand->shift != 16)
1413 {
1414 as_bad ("zdaoff() relocation used on an instruction which does not support it");
1415 return BFD_RELOC_64; /* Used to indicate an error condition. */
1416 }
936a8f55
NC
1417
1418 return BFD_RELOC_V850_ZDA_16_16_OFFSET;
c6aa56bc
C
1419}
1420
936a8f55
NC
1421static bfd_reloc_code_real_type
1422handle_tdaoff (const struct v850_operand * operand)
1423{
1424 if (operand == NULL) return BFD_RELOC_V850_TDA_7_7_OFFSET; /* data item, not an instruction. */
1425 if (operand->bits == 6 && operand->shift == 1) return BFD_RELOC_V850_TDA_6_8_OFFSET; /* sld.w/sst.w, operand: D8_6 */
1426 /* start-sanitize-v850e */
1427 if (operand->bits == 4 && operand->insert != NULL) return BFD_RELOC_V850_TDA_4_5_OFFSET; /* sld.hu, operand: D5-4 */
1428 if (operand->bits == 4 && operand->insert == NULL) return BFD_RELOC_V850_TDA_4_4_OFFSET; /* sld.bu, operand: D4 */
1429 /* end-sanitize-v850e */
1430 if (operand->bits == 16 && operand->shift == 16) return BFD_RELOC_V850_TDA_16_16_OFFSET; /* set1 & chums, operands: D16 */
1431
6df3c45f
NC
1432 if (operand->bits != 7)
1433 {
1434 as_bad ("tdaoff() relocation used on an instruction which does not support it");
1435 return BFD_RELOC_64; /* Used to indicate an error condition. */
1436 }
936a8f55
NC
1437
1438 return operand->insert != NULL
1439 ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7 */
1440 : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, opreand: D7 */
1441}
ccf10718
NC
1442
1443/* Warning: The code in this function relies upon the definitions
1444 in the v850_operands[] array (defined in opcodes/v850-opc.c)
9153e643 1445 matching the hard coded values contained herein. */
ccf10718 1446
c84615bc 1447static bfd_reloc_code_real_type
ccf10718 1448v850_reloc_prefix (const struct v850_operand * operand)
c6aa56bc 1449{
ccf10718
NC
1450 boolean paren_skipped = false;
1451
1452
1453 /* Skip leading opening parenthesis. */
1454 if (* input_line_pointer == '(')
1455 {
1456 ++ input_line_pointer;
1457 paren_skipped = true;
1458 }
c6aa56bc 1459
936a8f55
NC
1460#define CHECK_(name, reloc) \
1461 if (strncmp (input_line_pointer, name##"(", strlen (name) + 1) == 0) \
1462 { \
1463 input_line_pointer += strlen (name); \
1464 return reloc; \
548ddc71 1465 }
ccf10718 1466
936a8f55
NC
1467 CHECK_ ("hi0", BFD_RELOC_HI16);
1468 CHECK_ ("hi", BFD_RELOC_HI16_S);
1469 CHECK_ ("lo", BFD_RELOC_LO16);
1470 CHECK_ ("sdaoff", handle_sdaoff (operand));
1471 CHECK_ ("zdaoff", handle_zdaoff (operand));
1472 CHECK_ ("tdaoff", handle_tdaoff (operand));
c84615bc 1473
936a8f55 1474/* start-sanitize-v850e */
c2806093 1475 CHECK_ ("hilo", BFD_RELOC_32);
936a8f55
NC
1476 CHECK_ ("ctoff", handle_ctoff (operand));
1477/* end-sanitize-v850e */
1478
1479 /* Restore skipped parenthesis. */
ccf10718 1480 if (paren_skipped)
ccf10718
NC
1481 -- input_line_pointer;
1482
c84615bc
C
1483 return BFD_RELOC_UNUSED;
1484}
c6aa56bc 1485
c6aa56bc
C
1486void
1487md_assemble (str)
035d8553 1488 char * str;
c6aa56bc 1489{
035d8553
NC
1490 char * s;
1491 char * start_of_operands;
1492 struct v850_opcode * opcode;
1493 struct v850_opcode * next_opcode;
1494 const unsigned char * opindex_ptr;
1495 int next_opindex;
1496 int relaxable;
1497 unsigned long insn;
1498 unsigned long insn_size;
1499 char * f;
1500 int i;
1501 int match;
035d8553
NC
1502 boolean extra_data_after_insn = false;
1503 unsigned extra_data_len;
1504 unsigned long extra_data;
cf735d2a 1505 char * saved_input_line_pointer;
c2806093 1506
c6aa56bc
C
1507 /* Get the opcode. */
1508 for (s = str; *s != '\0' && ! isspace (*s); s++)
035d8553
NC
1509 continue;
1510
c6aa56bc
C
1511 if (*s != '\0')
1512 *s++ = '\0';
1513
1514 /* find the first opcode with the proper name */
1515 opcode = (struct v850_opcode *)hash_find (v850_hash, str);
1516 if (opcode == NULL)
1517 {
1518 as_bad ("Unrecognized opcode: `%s'", str);
035d8553 1519 ignore_rest_of_line ();
c6aa56bc
C
1520 return;
1521 }
1522
1523 str = s;
cf735d2a
NC
1524 while (isspace (* str))
1525 ++ str;
c6aa56bc 1526
035d8553 1527 start_of_operands = str;
c6aa56bc 1528
cf735d2a
NC
1529 saved_input_line_pointer = input_line_pointer;
1530
035d8553 1531 for (;;)
c6aa56bc 1532 {
035d8553 1533 const char * errmsg = NULL;
1510cd39 1534
d30a2be4
NC
1535 match = 0;
1536
1537 if ((opcode->processors & processor_mask) == 0)
1538 {
00fd8294 1539 errmsg = "Target processor does not support this instruction.";
d30a2be4
NC
1540 goto error;
1541 }
1542
a334533c 1543 relaxable = 0;
1510cd39 1544 fc = 0;
1510cd39 1545 next_opindex = 0;
d5974c57 1546 insn = opcode->opcode;
035d8553
NC
1547 extra_data_after_insn = false;
1548
1549 input_line_pointer = str = start_of_operands;
1550
1510cd39 1551 for (opindex_ptr = opcode->operands; *opindex_ptr != 0; opindex_ptr++)
c6aa56bc 1552 {
035d8553
NC
1553 const struct v850_operand * operand;
1554 char * hold;
1555 expressionS ex;
ccf10718 1556 bfd_reloc_code_real_type reloc;
c6aa56bc 1557
1510cd39 1558 if (next_opindex == 0)
c6aa56bc 1559 {
5f044499 1560 operand = & v850_operands[ * opindex_ptr ];
1510cd39
C
1561 }
1562 else
1563 {
5f044499 1564 operand = & v850_operands[ next_opindex ];
1510cd39 1565 next_opindex = 0;
c6aa56bc
C
1566 }
1567
1510cd39
C
1568 errmsg = NULL;
1569
1570 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
1571 ++str;
1572
a334533c
JL
1573 if (operand->flags & V850_OPERAND_RELAX)
1574 relaxable = 1;
1575
1510cd39
C
1576 /* Gather the operand. */
1577 hold = input_line_pointer;
1578 input_line_pointer = str;
035d8553 1579
c84615bc 1580 /* lo(), hi(), hi0(), etc... */
ccf10718 1581 if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED)
c84615bc 1582 {
6df3c45f
NC
1583 if (reloc == BFD_RELOC_64) /* This is a fake reloc, used to indicate an error condition. */
1584 {
1585 match = 1;
1586 goto error;
1587 }
1588
035d8553 1589 expression (& ex);
c84615bc 1590
c84615bc
C
1591 if (ex.X_op == O_constant)
1592 {
1593 switch (reloc)
1594 {
920b87c4
NC
1595 case BFD_RELOC_V850_ZDA_16_16_OFFSET:
1596 /* To cope with "not1 7, zdaoff(0xfffff006)[r0]" and the like. */
1597 /* Fall through. */
1598
c84615bc 1599 case BFD_RELOC_LO16:
d3bbd9dc
JL
1600 {
1601 /* Truncate, then sign extend the value. */
f483cb11 1602 ex.X_add_number = SEXT16 (ex.X_add_number);
d3bbd9dc
JL
1603 break;
1604 }
c84615bc
C
1605
1606 case BFD_RELOC_HI16:
15d8ae9d
JL
1607 {
1608 /* Truncate, then sign extend the value. */
f483cb11 1609 ex.X_add_number = SEXT16 (ex.X_add_number >> 16);
15d8ae9d
JL
1610 break;
1611 }
c84615bc
C
1612
1613 case BFD_RELOC_HI16_S:
15d8ae9d
JL
1614 {
1615 /* Truncate, then sign extend the value. */
1616 int temp = (ex.X_add_number >> 16) & 0xffff;
1617
1618 temp += (ex.X_add_number >> 15) & 1;
1619
f483cb11 1620 ex.X_add_number = SEXT16 (temp);
15d8ae9d
JL
1621 break;
1622 }
9153e643
NC
1623
1624/* start-sanitize-v850e */
1625 case BFD_RELOC_32:
1626 if ((operand->flags & V850E_IMMEDIATE32) == 0)
1627 {
1628 errmsg = "use bigger instruction";
1629 goto error;
1630 }
1631
1632 extra_data_after_insn = true;
1633 extra_data_len = 4;
1634 extra_data = ex.X_add_number;
1635 ex.X_add_number = 0;
1636 break;
1637/* end-sanitize-v850e */
920b87c4 1638
f964b01d 1639 default:
920b87c4
NC
1640 fprintf (stderr, "reloc: %d\n", reloc);
1641 as_bad ("AAARG -> unhandled constant reloc");
f964b01d 1642 break;
c84615bc
C
1643 }
1644
1645 insn = v850_insert_operand (insn, operand, ex.X_add_number,
1646 (char *) NULL, 0);
1647 }
1648 else
1649 {
9153e643
NC
1650 if (reloc == BFD_RELOC_32)
1651 {
1652 if ((operand->flags & V850E_IMMEDIATE32) == 0)
1653 {
1654 errmsg = "use bigger instruction";
1655 goto error;
1656 }
1657
1658 extra_data_after_insn = true;
1659 extra_data_len = 4;
1660 extra_data = ex.X_add_number;
1661 ex.X_add_number = 0;
1662 }
1663
c84615bc
C
1664 if (fc > MAX_INSN_FIXUPS)
1665 as_fatal ("too many fixups");
1666
ccf10718
NC
1667 fixups[ fc ].exp = ex;
1668 fixups[ fc ].opindex = * opindex_ptr;
1669 fixups[ fc ].reloc = reloc;
c84615bc
C
1670 fc++;
1671 }
1672 }
1673 else
1674 {
035d8553
NC
1675 errmsg = NULL;
1676
a334533c 1677 if ((operand->flags & V850_OPERAND_REG) != 0)
c6aa56bc 1678 {
035d8553 1679 if (!register_name (& ex))
a334533c
JL
1680 {
1681 errmsg = "invalid register name";
a334533c 1682 }
5f044499
NC
1683
1684 if ((operand->flags & V850_NOT_R0)
1685 && ex.X_add_number == 0)
1686 {
1687 errmsg = "register r0 cannot be used here";
1688 }
c6aa56bc 1689 }
a334533c 1690 else if ((operand->flags & V850_OPERAND_SRG) != 0)
0e8f9bd1 1691 {
d4b2cc56
NC
1692 if (!system_register_name (& ex, true
1693 /* start-sanitize-v850e */
1694 , false
1695 /* end-sanitize-v850e */
1696 ))
a334533c 1697 {
ccf10718 1698 errmsg = "invalid system register name";
a334533c 1699 }
0e8f9bd1 1700 }
a334533c 1701 else if ((operand->flags & V850_OPERAND_EP) != 0)
88b47a85 1702 {
035d8553
NC
1703 char * start = input_line_pointer;
1704 char c = get_symbol_end ();
1705
a334533c
JL
1706 if (strcmp (start, "ep") != 0 && strcmp (start, "r30") != 0)
1707 {
1708 /* Put things back the way we found them. */
1709 *input_line_pointer = c;
1710 input_line_pointer = start;
1711 errmsg = "expected EP register";
1712 goto error;
1713 }
035d8553 1714
88b47a85 1715 *input_line_pointer = c;
a334533c
JL
1716 str = input_line_pointer;
1717 input_line_pointer = hold;
1718
1719 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
1720 ++str;
1721 continue;
1722 }
1723 else if ((operand->flags & V850_OPERAND_CC) != 0)
1724 {
035d8553 1725 if (!cc_name (& ex))
a334533c
JL
1726 {
1727 errmsg = "invalid condition code name";
a334533c
JL
1728 }
1729 }
9153e643 1730/* start-sanitize-v850e */
035d8553
NC
1731 else if (operand->flags & V850E_PUSH_POP)
1732 {
cf735d2a 1733 errmsg = parse_register_list (& insn, operand);
035d8553
NC
1734
1735 /* The parse_register_list() function has already done everything, so fake a dummy expression. */
1736 ex.X_op = O_constant;
1737 ex.X_add_number = 0;
1738 }
1739 else if (operand->flags & V850E_IMMEDIATE16)
1740 {
1741 expression (& ex);
1742
1743 if (ex.X_op != O_constant)
1744 errmsg = "constant expression expected";
1745 else if (ex.X_add_number & 0xffff0000)
1746 {
1747 if (ex.X_add_number & 0xffff)
1748 errmsg = "constant too big to fit into instruction";
1749 else if ((insn & 0x001fffc0) == 0x00130780)
1750 ex.X_add_number >>= 16;
1751 else
1752 errmsg = "constant too big to fit into instruction";
1753 }
1754
1755 extra_data_after_insn = true;
1756 extra_data_len = 2;
1757 extra_data = ex.X_add_number;
1758 ex.X_add_number = 0;
1759 }
1760 else if (operand->flags & V850E_IMMEDIATE32)
1761 {
1762 expression (& ex);
1763
1764 if (ex.X_op != O_constant)
1765 errmsg = "constant expression expected";
1766
1767 extra_data_after_insn = true;
1768 extra_data_len = 4;
1769 extra_data = ex.X_add_number;
1770 ex.X_add_number = 0;
1771 }
9153e643 1772/* end-sanitize-v850e */
d4b2cc56 1773 else if (register_name (& ex)
a334533c
JL
1774 && (operand->flags & V850_OPERAND_REG) == 0)
1775 {
d4b2cc56
NC
1776 /* It is possible that an alias has been defined that
1777 matches a register name. For example the code may
1778 include a ".set ZERO, 0" directive, which matches
1779 the register name "zero". Attempt to reparse the
1780 field as an expression, and only complain if we
1781 cannot generate a constant. */
1782
1783 input_line_pointer = str;
1784
1785 expression (& ex);
1786
1787 if (ex.X_op != O_constant)
1788 errmsg = "syntax error: register not expected";
88b47a85 1789 }
d4b2cc56
NC
1790 else if (system_register_name (& ex, false
1791 /* start-sanitize-v850e */
1792 , false
1793 /* end-sanitize-v850e */
1794 )
a334533c 1795 && (operand->flags & V850_OPERAND_SRG) == 0)
c9f1b2d9 1796 {
a334533c 1797 errmsg = "syntax error: system register not expected";
c9f1b2d9 1798 }
a334533c
JL
1799 else if (cc_name (&ex)
1800 && (operand->flags & V850_OPERAND_CC) == 0)
1510cd39 1801 {
a334533c 1802 errmsg = "syntax error: condition code not expected";
1510cd39 1803 }
a334533c
JL
1804 else
1805 {
035d8553
NC
1806 expression (& ex);
1807/* start-sanitize-v850e */
1808 /* Special case:
1809 If we are assembling a MOV instruction (or a CALLT.... :-)
1810 and the immediate value does not fit into the bits available
035d8553
NC
1811 then create a fake error so that the next MOV instruction
1812 will be selected. This one has a 32 bit immediate field. */
1813
1814 if (((insn & 0x07e0) == 0x0200)
1815 && ex.X_op == O_constant
a365cd79 1816 && (ex.X_add_number < (- (1 << (operand->bits - 1))) || ex.X_add_number > ((1 << operand->bits) - 1)))
035d8553
NC
1817 errmsg = "use bigger instruction";
1818/* end-sanitize-v850e */
a334533c
JL
1819 }
1820
035d8553
NC
1821 if (errmsg)
1822 goto error;
a365cd79 1823
c2806093 1824/* fprintf (stderr, " insn: %x, operand %d, op: %d, add_number: %d\n", insn, opindex_ptr - opcode->operands, ex.X_op, ex.X_add_number); */
a365cd79 1825
a334533c
JL
1826 switch (ex.X_op)
1827 {
1828 case O_illegal:
1829 errmsg = "illegal operand";
1830 goto error;
1831 case O_absent:
1832 errmsg = "missing operand";
1833 goto error;
1834 case O_register:
1835 if ((operand->flags & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
1836 {
1837 errmsg = "invalid operand";
1838 goto error;
1839 }
a334533c
JL
1840 insn = v850_insert_operand (insn, operand, ex.X_add_number,
1841 (char *) NULL, 0);
1842 break;
1843
1844 case O_constant:
1845 insn = v850_insert_operand (insn, operand, ex.X_add_number,
1846 (char *) NULL, 0);
1847 break;
1848
1849 default:
1850 /* We need to generate a fixup for this expression. */
1851 if (fc >= MAX_INSN_FIXUPS)
1852 as_fatal ("too many fixups");
2d278484 1853
ccf10718
NC
1854 fixups[ fc ].exp = ex;
1855 fixups[ fc ].opindex = * opindex_ptr;
1856 fixups[ fc ].reloc = BFD_RELOC_UNUSED;
a334533c
JL
1857 ++fc;
1858 break;
1859 }
c84615bc
C
1860 }
1861
1862 str = input_line_pointer;
1863 input_line_pointer = hold;
1864
d3bbd9dc
JL
1865 while (*str == ' ' || *str == ',' || *str == '[' || *str == ']'
1866 || *str == ')')
1510cd39
C
1867 ++str;
1868 }
1869 match = 1;
1870
1871 error:
1872 if (match == 0)
1873 {
1874 next_opcode = opcode + 1;
28e1e54d 1875 if (next_opcode->name != NULL && strcmp (next_opcode->name, opcode->name) == 0)
1510cd39
C
1876 {
1877 opcode = next_opcode;
1878 continue;
1879 }
1880
ccf10718 1881 as_bad (errmsg);
035d8553 1882 ignore_rest_of_line ();
cf735d2a 1883 input_line_pointer = saved_input_line_pointer;
1510cd39
C
1884 return;
1885 }
1886 break;
1887 }
1888
c6aa56bc
C
1889 while (isspace (*str))
1890 ++str;
1891
1892 if (*str != '\0')
1893 as_bad ("junk at end of line: `%s'", str);
1510cd39
C
1894
1895 input_line_pointer = str;
c6aa56bc 1896
c2806093
NC
1897 /* Write out the instruction. */
1898
a334533c
JL
1899 if (relaxable && fc > 0)
1900 {
a334533c 1901 insn_size = 2;
a334533c 1902 fc = 0;
c2806093
NC
1903
1904 if (!strcmp (opcode->name, "br"))
1905 {
1906 f = frag_var (rs_machine_dependent, 4, 2, 2,
1907 fixups[0].exp.X_add_symbol,
1908 fixups[0].exp.X_add_number,
1909 (char *)fixups[0].opindex);
1910 md_number_to_chars (f, insn, insn_size);
1911 md_number_to_chars (f + 2, 0, 2);
1912 }
1913 else
1914 {
1915 f = frag_var (rs_machine_dependent, 6, 4, 0,
1916 fixups[0].exp.X_add_symbol,
1917 fixups[0].exp.X_add_number,
1918 (char *)fixups[0].opindex);
1919 md_number_to_chars (f, insn, insn_size);
1920 md_number_to_chars (f + 2, 0, 4);
1921 }
a334533c 1922 }
035d8553 1923 else
a334533c 1924 {
c2806093 1925 /* Four byte insns have an opcode with the two high bits on. */
035d8553
NC
1926 if ((insn & 0x0600) == 0x0600)
1927 insn_size = 4;
1928 else
1929 insn_size = 2;
1930
19f40fdc 1931/* start-sanitize-v850e */
035d8553
NC
1932 /* Special case: 32 bit MOV */
1933 if ((insn & 0xffe0) == 0x0620)
1934 insn_size = 2;
210c24d6 1935/* end-sanitize-v850e */
035d8553 1936
a334533c 1937 f = frag_more (insn_size);
035d8553 1938
a334533c 1939 md_number_to_chars (f, insn, insn_size);
035d8553
NC
1940
1941 if (extra_data_after_insn)
1942 {
9153e643 1943 f = frag_more (extra_data_len);
ccf10718 1944
9153e643 1945 md_number_to_chars (f, extra_data, extra_data_len);
035d8553
NC
1946
1947 extra_data_after_insn = false;
1948 }
a334533c 1949 }
c84615bc
C
1950
1951 /* Create any fixups. At this point we do not use a
1952 bfd_reloc_code_real_type, but instead just use the
1953 BFD_RELOC_UNUSED plus the operand index. This lets us easily
1954 handle fixups for any operand type, although that is admittedly
1955 not a very exciting feature. We pick a BFD reloc type in
ccf10718 1956 md_apply_fix. */
c84615bc
C
1957 for (i = 0; i < fc; i++)
1958 {
ccf10718 1959 const struct v850_operand * operand;
9153e643
NC
1960 bfd_reloc_code_real_type reloc;
1961
ccf10718 1962 operand = & v850_operands[ fixups[i].opindex ];
9153e643
NC
1963
1964 reloc = fixups[i].reloc;
ccf10718 1965
9153e643 1966 if (reloc != BFD_RELOC_UNUSED)
c84615bc 1967 {
9153e643 1968 reloc_howto_type * reloc_howto = bfd_reloc_type_lookup (stdoutput, reloc);
ccf10718
NC
1969 int size;
1970 int address;
1971 fixS * fixP;
c84615bc
C
1972
1973 if (!reloc_howto)
1974 abort();
1975
1976 size = bfd_get_reloc_size (reloc_howto);
8ea15b86 1977
ccf10718 1978 if (size != 2 && size != 4) /* XXX this will abort on an R_V850_8 reloc - is this reloc actually used ? */
c84615bc
C
1979 abort();
1980
ccf10718 1981 address = (f - frag_now->fr_literal) + insn_size - size;
9153e643
NC
1982
1983 if (reloc == BFD_RELOC_32)
1984 {
1985 address += 2;
1986 }
1987
ccf10718
NC
1988 fixP = fix_new_exp (frag_now, address, size,
1989 & fixups[i].exp,
c84615bc 1990 reloc_howto->pc_relative,
9153e643 1991 reloc);
d222309a 1992
9153e643 1993 switch (reloc)
d222309a
JL
1994 {
1995 case BFD_RELOC_LO16:
1996 case BFD_RELOC_HI16:
1997 case BFD_RELOC_HI16_S:
1998 fixP->fx_no_overflow = 1;
1999 break;
2000 }
c84615bc
C
2001 }
2002 else
2003 {
2d278484
NC
2004 fix_new_exp (
2005 frag_now,
2006 f - frag_now->fr_literal, 4,
ccf10718 2007 & fixups[i].exp,
c84615bc 2008 1 /* FIXME: V850_OPERAND_RELATIVE ??? */,
2d278484
NC
2009 (bfd_reloc_code_real_type) (fixups[i].opindex + (int) BFD_RELOC_UNUSED)
2010 );
c84615bc
C
2011 }
2012 }
ccf10718 2013
cf735d2a 2014 input_line_pointer = saved_input_line_pointer;
c6aa56bc
C
2015}
2016
2017
ccf10718
NC
2018/* If while processing a fixup, a reloc really needs to be created */
2019/* then it is done here. */
c6aa56bc
C
2020
2021arelent *
2022tc_gen_reloc (seg, fixp)
ccf10718
NC
2023 asection * seg;
2024 fixS * fixp;
c6aa56bc 2025{
ccf10718
NC
2026 arelent * reloc;
2027
2028 reloc = (arelent *) xmalloc (sizeof (arelent));
2029 reloc->sym_ptr_ptr = & fixp->fx_addsy->bsym;
2030 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2031 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
9153e643 2032
c6aa56bc
C
2033 if (reloc->howto == (reloc_howto_type *) NULL)
2034 {
2035 as_bad_where (fixp->fx_file, fixp->fx_line,
2036 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
9153e643
NC
2037
2038 xfree (reloc);
2039
c6aa56bc
C
2040 return NULL;
2041 }
ccf10718 2042
c6aa56bc 2043 reloc->addend = fixp->fx_addnumber;
ccf10718 2044
c6aa56bc
C
2045 return reloc;
2046}
2047
a334533c 2048/* Assume everything will fit in two bytes, then expand as necessary. */
c6aa56bc
C
2049int
2050md_estimate_size_before_relax (fragp, seg)
ccf10718
NC
2051 fragS * fragp;
2052 asection * seg;
c6aa56bc 2053{
c2806093
NC
2054 if (fragp->fr_subtype == 0)
2055 fragp->fr_var = 4;
2056 else if (fragp->fr_subtype == 2)
2057 fragp->fr_var = 2;
2058 else
2059 abort ();
a334533c 2060 return 2;
c6aa56bc
C
2061}
2062
2063long
0f8e50bb 2064md_pcrel_from (fixp)
ccf10718 2065 fixS * fixp;
c6aa56bc 2066{
f964b01d
JL
2067 /* If the symbol is undefined, or in a section other than our own,
2068 then let the linker figure it out. */
0f8e50bb 2069 if (fixp->fx_addsy != (symbolS *) NULL && ! S_IS_DEFINED (fixp->fx_addsy))
c84615bc
C
2070 {
2071 /* The symbol is undefined. Let the linker figure it out. */
2072 return 0;
2073 }
2074 return fixp->fx_frag->fr_address + fixp->fx_where;
c6aa56bc
C
2075}
2076
2077int
2078md_apply_fix3 (fixp, valuep, seg)
ccf10718
NC
2079 fixS * fixp;
2080 valueT * valuep;
2081 segT seg;
c6aa56bc 2082{
c6aa56bc 2083 valueT value;
ccf10718 2084 char * where;
c6aa56bc
C
2085
2086 if (fixp->fx_addsy == (symbolS *) NULL)
2087 {
ccf10718 2088 value = * valuep;
c6aa56bc
C
2089 fixp->fx_done = 1;
2090 }
2091 else if (fixp->fx_pcrel)
ccf10718 2092 value = * valuep;
c6aa56bc
C
2093 else
2094 {
2095 value = fixp->fx_offset;
2096 if (fixp->fx_subsy != (symbolS *) NULL)
2097 {
2098 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
2099 value -= S_GET_VALUE (fixp->fx_subsy);
2100 else
2101 {
2102 /* We don't actually support subtracting a symbol. */
2103 as_bad_where (fixp->fx_file, fixp->fx_line,
2104 "expression too complex");
2105 }
2106 }
2107 }
c6aa56bc 2108
c84615bc
C
2109 if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
2110 {
ccf10718
NC
2111 int opindex;
2112 const struct v850_operand * operand;
ccf10718 2113 unsigned long insn;
c84615bc
C
2114
2115 opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
ccf10718 2116 operand = & v850_operands[ opindex ];
c84615bc
C
2117
2118 /* Fetch the instruction, insert the fully resolved operand
74dd0c07
JL
2119 value, and stuff the instruction back again.
2120
2121 Note the instruction has been stored in little endian
2122 format! */
c84615bc 2123 where = fixp->fx_frag->fr_literal + fixp->fx_where;
74dd0c07 2124
ccf10718 2125 insn = bfd_getl32 ((unsigned char *) where);
c84615bc
C
2126 insn = v850_insert_operand (insn, operand, (offsetT) value,
2127 fixp->fx_file, fixp->fx_line);
ccf10718 2128 bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
c84615bc
C
2129
2130 if (fixp->fx_done)
2131 {
2132 /* Nothing else to do here. */
2133 return 1;
2134 }
c6aa56bc 2135
c84615bc
C
2136 /* Determine a BFD reloc value based on the operand information.
2137 We are only prepared to turn a few of the operands into relocs. */
c6aa56bc 2138
c84615bc
C
2139 if (operand->bits == 22)
2140 fixp->fx_r_type = BFD_RELOC_V850_22_PCREL;
2141 else if (operand->bits == 9)
2142 fixp->fx_r_type = BFD_RELOC_V850_9_PCREL;
2143 else
2144 {
9153e643
NC
2145 /* fprintf (stderr, "bits: %d, insn: %x\n", operand->bits, insn); */
2146
c84615bc
C
2147 as_bad_where(fixp->fx_file, fixp->fx_line,
2148 "unresolved expression that must be resolved");
2149 fixp->fx_done = 1;
2150 return 1;
2151 }
2152 }
2d56269e
JL
2153 else if (fixp->fx_done)
2154 {
2155 /* We still have to insert the value into memory! */
2156 where = fixp->fx_frag->fr_literal + fixp->fx_where;
c2806093 2157
2d56269e
JL
2158 if (fixp->fx_size == 1)
2159 *where = value & 0xff;
9153e643 2160 else if (fixp->fx_size == 2)
ccf10718 2161 bfd_putl16 (value & 0xffff, (unsigned char *) where);
9153e643 2162 else if (fixp->fx_size == 4)
ccf10718 2163 bfd_putl32 (value, (unsigned char *) where);
2d56269e 2164 }
ccf10718 2165
c6aa56bc
C
2166 fixp->fx_addnumber = value;
2167 return 1;
c6aa56bc
C
2168}
2169
2170\f
2171/* Insert an operand value into an instruction. */
2172
2173static unsigned long
2174v850_insert_operand (insn, operand, val, file, line)
2175 unsigned long insn;
035d8553 2176 const struct v850_operand * operand;
c6aa56bc
C
2177 offsetT val;
2178 char *file;
2179 unsigned int line;
2180{
74dd0c07
JL
2181 if (operand->insert)
2182 {
035d8553
NC
2183 const char * message = NULL;
2184
2185 insn = (*operand->insert) (insn, val, & message);
74dd0c07
JL
2186 if (message != NULL)
2187 {
2188 if (file == (char *) NULL)
2189 as_warn (message);
2190 else
2191 as_warn_where (file, line, message);
2192 }
2193 }
2194 else
b0b262f7
NC
2195 {
2196 if (operand->bits != 32)
2197 {
2198 long min, max;
2199 offsetT test;
2200
2201 if ((operand->flags & V850_OPERAND_SIGNED) != 0)
2202 {
2203 if (! warn_signed_overflows)
2204 max = (1 << operand->bits) - 1;
2205 else
2206 max = (1 << (operand->bits - 1)) - 1;
2207
2208 min = - (1 << (operand->bits - 1));
2209 }
2210 else
2211 {
2212 max = (1 << operand->bits) - 1;
2213
2214 if (! warn_unsigned_overflows)
2215 min = - (1 << (operand->bits - 1));
2216 else
2217 min = 0;
2218 }
2219
2220 test = val;
2221
2222 if (test < (offsetT) min || test > (offsetT) max)
2223 {
2224 const char * err = "operand out of range (%s not between %ld and %ld)";
2225 char buf[100];
2226
d4b2cc56
NC
2227 /* Restore min and mix to expected values for decimal ranges. */
2228 if ((operand->flags & V850_OPERAND_SIGNED) && ! warn_signed_overflows)
2229 max = (1 << (operand->bits - 1)) - 1;
2230
2231 if (! (operand->flags & V850_OPERAND_SIGNED)
2232 && ! warn_unsigned_overflows)
2233 min = 0;
2234
b0b262f7
NC
2235 sprint_value (buf, test);
2236 if (file == (char *) NULL)
2237 as_warn (err, buf, min, max);
2238 else
2239 as_warn_where (file, line, err, buf, min, max);
2240 }
2241 }
2242
2243 insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
2244 }
035d8553 2245
c6aa56bc
C
2246 return insn;
2247}
10fba7f1
JL
2248
2249/* Parse a cons expression. We have to handle hi(), lo(), etc
2250 on the v850. */
2251void
2252parse_cons_expression_v850 (exp)
2253 expressionS *exp;
2254{
2255 /* See if there's a reloc prefix like hi() we have to handle. */
ccf10718 2256 hold_cons_reloc = v850_reloc_prefix (NULL);
10fba7f1
JL
2257
2258 /* Do normal expression parsing. */
2259 expression (exp);
10fba7f1
JL
2260}
2261
2262/* Create a fixup for a cons expression. If parse_cons_expression_v850
2263 found a reloc prefix, then we use that reloc, else we choose an
2264 appropriate one based on the size of the expression. */
2265void
2266cons_fix_new_v850 (frag, where, size, exp)
2267 fragS *frag;
2268 int where;
2269 int size;
2270 expressionS *exp;
2271{
2272 if (hold_cons_reloc == BFD_RELOC_UNUSED)
2273 {
2274 if (size == 4)
2275 hold_cons_reloc = BFD_RELOC_32;
2276 if (size == 2)
2277 hold_cons_reloc = BFD_RELOC_16;
2278 if (size == 1)
2279 hold_cons_reloc = BFD_RELOC_8;
2280 }
2281
2282 if (exp != NULL)
2283 fix_new_exp (frag, where, size, exp, 0, hold_cons_reloc);
2284 else
2285 fix_new (frag, where, size, NULL, 0, 0, hold_cons_reloc);
2286}
This page took 0.16776 seconds and 4 git commands to generate.