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