b10bed64c9747c922cfaac6f29fea6458e8cd19b
[deliverable/binutils-gdb.git] / gas / config / tc-d10v.c
1 /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
2
3 Copyright (C) 1996 Free Software Foundation.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #include "as.h"
25 #include "subsegs.h"
26 #include "opcode/d10v.h"
27 #include "elf/ppc.h"
28
29 const char comment_chars[] = "#;";
30 const char line_comment_chars[] = "#";
31 const char line_separator_chars[] = "";
32 const char *md_shortopts = "";
33 const char EXP_CHARS[] = "eE";
34 const char FLT_CHARS[] = "dD";
35
36
37 /* fixups */
38 #define MAX_INSN_FIXUPS (5)
39 struct d10v_fixup
40 {
41 expressionS exp;
42 bfd_reloc_code_real_type reloc;
43 };
44
45 typedef struct _fixups
46 {
47 int fc;
48 struct d10v_fixup fix[MAX_INSN_FIXUPS];
49 struct _fixups *next;
50 } Fixups;
51
52 static Fixups FixUps[2];
53 static Fixups *fixups;
54
55 /* local functions */
56 static int reg_name_search PARAMS ((char *name));
57 static int register_name PARAMS ((expressionS *expressionP));
58 static int postfix PARAMS ((char *p));
59 static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
60 static int get_operands PARAMS ((expressionS exp[]));
61 static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn));
62 static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
63 static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
64 static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
65 struct d10v_opcode *opcode2, unsigned long insn2, int exec_type, Fixups *fx));
66 static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
67 static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type,
68 offsetT value, int left));
69
70
71 struct option md_longopts[] = {
72 {NULL, no_argument, NULL, 0}
73 };
74 size_t md_longopts_size = sizeof(md_longopts);
75
76 /* The target specific pseudo-ops which we support. */
77 const pseudo_typeS md_pseudo_table[] =
78 {
79 { NULL, NULL, 0 }
80 };
81
82 /* Opcode hash table. */
83 static struct hash_control *d10v_hash;
84
85 /* reg_name_search does a binary search of the pre_defined_registers
86 array to see if "name" is a valid regiter name. Returns the register
87 number from the array on success, or -1 on failure. */
88
89 static int
90 reg_name_search (name)
91 char *name;
92 {
93 int middle, low, high;
94 int cmp;
95
96 low = 0;
97 high = reg_name_cnt() - 1;
98
99 do
100 {
101 middle = (low + high) / 2;
102 cmp = strcasecmp (name, pre_defined_registers[middle].name);
103 if (cmp < 0)
104 high = middle - 1;
105 else if (cmp > 0)
106 low = middle + 1;
107 else
108 return pre_defined_registers[middle].value;
109 }
110 while (low <= high);
111 return -1;
112 }
113
114 /* register_name() checks the string at input_line_pointer
115 to see if it is a valid register name */
116
117 static int
118 register_name (expressionP)
119 expressionS *expressionP;
120 {
121 int reg_number;
122 char c, *p = input_line_pointer;
123
124 while (*p && *p!='\n' && *p!='\r' && *p !=',' && *p!=' ' && *p!=')')
125 p++;
126
127 c = *p;
128 if (c)
129 *p++ = 0;
130
131 /* look to see if it's in the register table */
132 reg_number = reg_name_search (input_line_pointer);
133 if (reg_number >= 0)
134 {
135 expressionP->X_op = O_register;
136 /* temporarily store a pointer to the string here */
137 expressionP->X_op_symbol = (struct symbol *)input_line_pointer;
138 expressionP->X_add_number = reg_number;
139 input_line_pointer = p;
140 return 1;
141 }
142 if (c)
143 *(p-1) = c;
144 return 0;
145 }
146
147
148 static int
149 check_range (num, bits, sign)
150 unsigned long num;
151 int bits;
152 int sign;
153 {
154 long min, max;
155 int retval=0;
156
157 if (sign)
158 {
159 max = (1 << (bits - 1)) - 1;
160 min = - (1 << (bits - 1));
161 if (((long)num > max) || ((long)num < min))
162 retval = 1;
163 }
164 else
165 {
166 max = (1 << bits) - 1;
167 min = 0;
168 if ((num > max) || (num < min))
169 retval = 1;
170 }
171
172 return retval;
173 }
174
175
176 void
177 md_show_usage (stream)
178 FILE *stream;
179 {
180 fprintf(stream, "D10V options:\n\
181 none yet\n");
182 }
183
184 int
185 md_parse_option (c, arg)
186 int c;
187 char *arg;
188 {
189 return 0;
190 }
191
192 symbolS *
193 md_undefined_symbol (name)
194 char *name;
195 {
196 return 0;
197 }
198
199 char *
200 md_atof (type, litp, sizep)
201 int type;
202 char *litp;
203 int *sizep;
204 {
205 return "";
206 }
207
208 void
209 md_convert_frag (abfd, sec, fragP)
210 bfd *abfd;
211 asection *sec;
212 fragS *fragP;
213 {
214 printf ("call to md_convert_frag \n");
215 abort ();
216 }
217
218 valueT
219 md_section_align (seg, addr)
220 asection *seg;
221 valueT addr;
222 {
223 int align = bfd_get_section_alignment (stdoutput, seg);
224 return ((addr + (1 << align) - 1) & (-1 << align));
225 }
226
227
228 void
229 md_begin ()
230 {
231 char *prev_name = "";
232 struct d10v_opcode *opcode;
233 d10v_hash = hash_new();
234
235 /* Insert unique names into hash table. The D10v instruction set
236 has many identical opcode names that have different opcodes based
237 on the operands. This hash table then provides a quick index to
238 the first opcode with a particular name in the opcode table. */
239
240 for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++)
241 {
242 if (strcmp (prev_name, opcode->name))
243 {
244 prev_name = (char *)opcode->name;
245 hash_insert (d10v_hash, opcode->name, (char *) opcode);
246 }
247 }
248
249 fixups = &FixUps[0];
250 FixUps[0].next = &FixUps[1];
251 FixUps[1].next = &FixUps[0];
252 }
253
254
255 /* this function removes the postincrement or postdecrement
256 operator ( '+' or '-' ) from an expression */
257
258 static int postfix (p)
259 char *p;
260 {
261 while (*p != '-' && *p != '+')
262 {
263 if (*p==0 || *p=='\n' || *p=='\r')
264 break;
265 p++;
266 }
267
268 if (*p == '-')
269 {
270 *p = ' ';
271 return (-1);
272 }
273 if (*p == '+')
274 {
275 *p = ' ';
276 return (1);
277 }
278
279 return (0);
280 }
281
282
283 static bfd_reloc_code_real_type
284 get_reloc (op)
285 struct d10v_operand *op;
286 {
287 int bits = op->bits;
288
289 /* printf("get_reloc: bits=%d address=%d\n",bits,op->flags & OPERAND_ADDR); */
290 if (bits <= 4)
291 return (0);
292
293 if (op->flags & OPERAND_ADDR)
294 {
295 if (bits == 8)
296 return (BFD_RELOC_D10V_10_PCREL_R);
297 else
298 return (BFD_RELOC_D10V_18_PCREL);
299 }
300
301 return (BFD_RELOC_16);
302 }
303
304 /* get_operands parses a string of operands and returns
305 an array of expressions */
306
307 static int
308 get_operands (exp)
309 expressionS exp[];
310 {
311 char *p = input_line_pointer;
312 int numops = 0;
313 int post = 0;
314
315 while (*p)
316 {
317 while (*p == ' ' || *p == '\t' || *p == ',')
318 p++;
319 if (*p==0 || *p=='\n' || *p=='\r')
320 break;
321
322 if (*p == '@')
323 {
324 p++;
325 exp[numops].X_op = O_absent;
326 if (*p == '(')
327 {
328 p++;
329 exp[numops].X_add_number = OPERAND_ATPAR;
330 }
331 else if (*p == '-')
332 {
333 p++;
334 exp[numops].X_add_number = OPERAND_ATMINUS;
335 }
336 else
337 {
338 exp[numops].X_add_number = OPERAND_ATSIGN;
339 post = postfix (p);
340 }
341 numops++;
342 continue;
343 }
344
345 if (*p == ')')
346 {
347 /* just skip the trailing paren */
348 p++;
349 continue;
350 }
351
352 input_line_pointer = p;
353
354
355 /* check to see if it might be a register name */
356 if (!register_name (&exp[numops]))
357 {
358 /* parse as an expression */
359 expression (&exp[numops]);
360 }
361
362 if (exp[numops].X_op == O_illegal)
363 as_bad ("illegal operand");
364 else if (exp[numops].X_op == O_absent)
365 as_bad ("missing operand");
366
367 numops++;
368 p = input_line_pointer;
369 }
370
371 switch (post)
372 {
373 case -1: /* postdecrement mode */
374 exp[numops].X_op = O_absent;
375 exp[numops++].X_add_number = OPERAND_MINUS;
376 break;
377 case 1: /* postincrement mode */
378 exp[numops].X_op = O_absent;
379 exp[numops++].X_add_number = OPERAND_PLUS;
380 break;
381 }
382
383 exp[numops].X_op = 0;
384 return (numops);
385 }
386
387 static unsigned long
388 d10v_insert_operand (insn, op_type, value, left)
389 unsigned long insn;
390 int op_type;
391 offsetT value;
392 int left;
393 {
394 int shift, bits;
395
396 shift = d10v_operands[op_type].shift;
397 if (left)
398 shift += 15;
399
400 bits = d10v_operands[op_type].bits;
401
402 /* truncate to the proper number of bits */
403 /* FIXME: overflow checking here? */
404
405 if (check_range (value, bits, d10v_operands[op_type].flags & OPERAND_SIGNED))
406 as_bad("operand out of range: %d",value);
407
408 value &= 0x7FFFFFFF >> (31 - bits);
409 insn |= (value << shift);
410
411 return insn;
412 }
413
414
415 /* build_insn takes a pointer to the opcode entry in the opcode table
416 and the array of operand expressions and returns the instruction */
417
418 static unsigned long
419 build_insn (opcode, opers, insn)
420 struct d10v_opcode *opcode;
421 expressionS *opers;
422 unsigned long insn;
423 {
424 int i, bits, shift, flags, format;
425 unsigned int number;
426
427 /* the insn argument is only used for the DIVS kludge */
428 if (insn)
429 format = LONG_R;
430 else
431 {
432 insn = opcode->opcode;
433 format = opcode->format;
434 }
435
436 for (i=0;opcode->operands[i];i++)
437 {
438 flags = d10v_operands[opcode->operands[i]].flags;
439 bits = d10v_operands[opcode->operands[i]].bits;
440 shift = d10v_operands[opcode->operands[i]].shift;
441 number = opers[i].X_add_number;
442
443 if (flags & OPERAND_REG)
444 {
445 number &= REGISTER_MASK;
446 if (format == LONG_L)
447 shift += 15;
448 }
449
450 if (opers[i].X_op != O_register && opers[i].X_op != O_constant)
451 {
452 /* now create a fixup */
453
454 /*
455 printf("need a fixup: ");
456 print_expr_1(stdout,&opers[i]);
457 printf("\n");
458 */
459
460 if (fixups->fc >= MAX_INSN_FIXUPS)
461 as_fatal ("too many fixups");
462 fixups->fix[fixups->fc].exp = opers[i];
463
464 /* put the operand number here for now. We can look up
465 the reloc type and/or fixup the instruction in md_apply_fix() */
466 fixups->fix[fixups->fc].reloc = opcode->operands[i];
467 (fixups->fc)++;
468 }
469
470 /* truncate to the proper number of bits */
471 if ((opers[i].X_op == O_constant) && check_range (number, bits, flags & OPERAND_SIGNED))
472 as_bad("operand out of range: %d",number);
473 number &= 0x7FFFFFFF >> (31 - bits);
474 insn = insn | (number << shift);
475 }
476
477 /* kludge: for DIVS, we need to put the operands in twice */
478 /* on the second pass, format is changed to LONG_R to force */
479 /* the second set of operands to not be shifted over 15 */
480 if ((opcode->opcode == OPCODE_DIVS) && (format==LONG_L))
481 insn = build_insn (opcode, opers, insn);
482
483 return insn;
484 }
485
486 /* write out a long form instruction */
487 static void
488 write_long (opcode, insn, fx)
489 struct d10v_opcode *opcode;
490 unsigned long insn;
491 Fixups *fx;
492 {
493 int i;
494 char *f = frag_more(4);
495
496 insn |= FM11;
497 /* printf("INSN: %08x\n",insn); */
498 number_to_chars_bigendian (f, insn, 4);
499
500 for (i=0; i < fx->fc; i++)
501 {
502 if (get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]))
503 {
504 /*
505 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
506 print_expr_1(stdout,&(fx->fix[i].exp));
507 printf("\n");
508 */
509
510 fix_new_exp (frag_now,
511 f - frag_now->fr_literal,
512 4,
513 &(fx->fix[i].exp),
514 1,
515 fx->fix[i].reloc);
516 }
517 }
518 fx->fc = 0;
519 }
520
521
522 /* write out a short form instruction by itself */
523 static void
524 write_1_short (opcode, insn, fx)
525 struct d10v_opcode *opcode;
526 unsigned long insn;
527 Fixups *fx;
528 {
529 char *f = frag_more(4);
530 int i;
531
532 /* the other container needs to be NOP */
533 /* according to 4.3.1: for FM=00, sub-instructions performed only
534 by IU cannot be encoded in L-container. */
535 if (opcode->unit == IU)
536 insn |= FM00 | (NOP << 15); /* right container */
537 else
538 insn = FM00 | (insn << 15) | NOP; /* left container */
539
540 /* printf("INSN: %08x\n",insn); */
541 number_to_chars_bigendian (f, insn, 4);
542 for (i=0; i < fx->fc; i++)
543 {
544 if (get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]))
545 {
546 /*
547 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
548 print_expr_1(stdout,&(fx->fix[i].exp));
549 printf("\n");
550 */
551
552 fix_new_exp (frag_now,
553 f - frag_now->fr_literal,
554 4,
555 &(fx->fix[i].exp),
556 1,
557 fx->fix[i].reloc);
558 }
559 }
560 fx->fc = 0;
561 }
562
563 /* write out a short form instruction if possible */
564 /* return number of instructions not written out */
565 static int
566 write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
567 struct d10v_opcode *opcode1, *opcode2;
568 unsigned long insn1, insn2;
569 int exec_type;
570 Fixups *fx;
571 {
572 unsigned long insn;
573 char *f;
574 int i,j;
575
576 if(opcode1->exec_type == BRANCH_LINK)
577 {
578 /* subroutines must be called from 32-bit boundaries */
579 /* so the return address will be correct */
580 write_1_short (opcode1, insn1, fx->next);
581 return (1);
582 }
583
584 switch (exec_type)
585 {
586 case 0:
587 if (opcode1->unit == IU)
588 {
589 /* reverse sequential */
590 insn = FM10 | (insn2 << 15) | insn1;
591 }
592 else
593 {
594 insn = FM01 | (insn1 << 15) | insn2;
595 fx = fx->next;
596 }
597 break;
598 case 1: /* parallel */
599 insn = FM00 | (insn1 << 15) | insn2;
600 fx = fx->next;
601 break;
602 case 2: /* sequential */
603 insn = FM01 | (insn1 << 15) | insn2;
604 fx = fx->next;
605 break;
606 case 3: /* reverse sequential */
607 insn = FM10 | (insn1 << 15) | insn2;
608 break;
609 default:
610 as_fatal("unknown execution type passed to write_2_short()");
611 }
612
613 /* printf("INSN: %08x\n",insn); */
614 f = frag_more(4);
615 number_to_chars_bigendian (f, insn, 4);
616
617 for (j=0; j<2; j++)
618 {
619 bfd_reloc_code_real_type reloc;
620 for (i=0; i < fx->fc; i++)
621 {
622 reloc = get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]);
623 if (reloc)
624 {
625 if ( (reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0) )
626 fx->fix[i].reloc |= 1024;
627
628 /*
629 printf("fix_new_exp: where:%x reloc:%d\n ",f - frag_now->fr_literal,fx->fix[i].reloc);
630 print_expr_1(stdout,&(fx->fix[i].exp));
631 printf("\n");
632 */
633 fix_new_exp (frag_now,
634 f - frag_now->fr_literal,
635 4,
636 &(fx->fix[i].exp),
637 1,
638 fx->fix[i].reloc);
639 }
640 }
641 fx->fc = 0;
642 fx = fx->next;
643 }
644
645 return (0);
646 }
647
648
649 /* This is the main entry point for the machine-dependent assembler. str points to a
650 machine-dependent instruction. This function is supposed to emit the frags/bytes
651 it assembles to. For the D10V, it mostly handles the special VLIW parsing and packing
652 and leaves the difficult stuff to do_assemble().
653 */
654
655 static unsigned long prev_insn;
656 static struct d10v_opcode *prev_opcode = 0;
657 static subsegT prev_subseg;
658 static segT prev_seg;
659
660 void
661 md_assemble (str)
662 char *str;
663 {
664 struct d10v_opcode *opcode;
665 unsigned long insn;
666 int t=0;
667 char *str2;
668
669 /* printf("md_assemble: str=%s\n",str); */
670
671 /* look for the special multiple instruction seperators */
672 str2 = strstr (str, "||");
673 if (str2)
674 t = 1;
675 else
676 {
677 str2 = strstr (str, "->");
678 if (str2)
679 t = 2;
680 else
681 {
682 str2 = strstr (str, "<-");
683 if (str2)
684 t = 3;
685 }
686 }
687
688
689 /* str2 points to the seperator, if one */
690 if (str2)
691 {
692 *str2 = 0;
693
694 /* if two instructions are present and we already have one saved
695 then first write it out */
696 if (prev_opcode)
697 write_1_short (prev_opcode, prev_insn, fixups->next);
698
699 /* assemble first instruction and save it */
700 prev_insn = do_assemble (str, &prev_opcode);
701 fixups = fixups->next;
702 str = str2 + 2;
703 }
704
705 insn = do_assemble (str, &opcode);
706
707 /* if this is a long instruction, write it and any previous short instruction */
708 if (opcode->format & LONG_OPCODE)
709 {
710 if (t)
711 as_fatal("Unable to mix instructions as specified");
712 if (prev_opcode)
713 {
714 write_1_short (prev_opcode, prev_insn, fixups->next);
715 prev_opcode = NULL;
716 }
717 write_long (opcode, insn, fixups);
718 prev_opcode = NULL;
719 return;
720 }
721
722 if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, t, fixups) == 0))
723 {
724 /* no instructions saved */
725 prev_opcode = NULL;
726 }
727 else
728 {
729 if (t)
730 as_fatal("Unable to mix instructions as specified");
731 /* save off last instruction so it may be packed on next pass */
732 prev_opcode = opcode;
733 prev_insn = insn;
734 prev_seg = now_seg;
735 prev_subseg = now_subseg;
736 fixups = fixups->next;
737 }
738 }
739
740
741 static unsigned long
742 do_assemble (str, opcode)
743 char *str;
744 struct d10v_opcode **opcode;
745 {
746 struct d10v_opcode *next_opcode;
747 unsigned char *op_start, *save;
748 unsigned char *op_end;
749 char name[20];
750 int nlen = 0, i, match, numops;
751 expressionS myops[6];
752 unsigned long insn;
753
754 /* printf("do_assemble: str=%s\n",str); */
755
756 /* Drop leading whitespace */
757 while (*str == ' ')
758 str++;
759
760 /* find the opcode end */
761 for (op_start = op_end = (unsigned char *) (str);
762 *op_end
763 && nlen < 20
764 && !is_end_of_line[*op_end] && *op_end != ' ';
765 op_end++)
766 {
767 name[nlen] = op_start[nlen];
768 nlen++;
769 }
770 name[nlen] = 0;
771
772 if (nlen == 0)
773 as_bad ("can't find opcode ");
774
775 /* find the first opcode with the proper name */
776 *opcode = (struct d10v_opcode *)hash_find (d10v_hash, name);
777 if (*opcode == NULL)
778 {
779 as_fatal ("unknown opcode: %s",name);
780 return;
781 }
782
783 save = input_line_pointer;
784 input_line_pointer = op_end;
785
786 /* get all the operands and save them as expressions */
787 numops = get_operands (myops);
788
789 /* now see if the operand is a fake. If so, find the correct size */
790 /* instruction, if possible */
791 match = 0;
792 if ((*opcode)->format == OPCODE_FAKE)
793 {
794 int opnum = (*opcode)->operands[0];
795 if (myops[opnum].X_op == O_constant)
796 {
797 next_opcode=(*opcode)+1;
798 for (i=0; (*opcode)->operands[i+1]; i++)
799 {
800 int bits = d10v_operands[next_opcode->operands[opnum]].bits;
801 int flags = d10v_operands[next_opcode->operands[opnum]].flags;
802 if (!check_range (myops[opnum].X_add_number, bits, flags & OPERAND_SIGNED))
803 {
804 match = 1;
805 break;
806 }
807 next_opcode++;
808 }
809 }
810 else
811 {
812 /* not a constant, so use a long instruction */
813 next_opcode = (*opcode)+2;
814 match = 1;
815 }
816 if (match)
817 *opcode = next_opcode;
818 else
819 as_fatal ("value out of range");
820 }
821 else
822 {
823 /* now search the opcode table table for one with operands */
824 /* that match what we've got */
825 while (!match)
826 {
827 match = 1;
828 for (i = 0; (*opcode)->operands[i]; i++)
829 {
830 int flags = d10v_operands[(*opcode)->operands[i]].flags;
831 int X_op = myops[i].X_op;
832 int num = myops[i].X_add_number;
833
834 if (X_op==0)
835 {
836 match=0;
837 break;
838 }
839
840 if (flags & OPERAND_REG)
841 {
842 if ((X_op != O_register) ||
843 ((flags & OPERAND_ACC) != (num & OPERAND_ACC)) ||
844 ((flags & OPERAND_FLAG) != (num & OPERAND_FLAG)) ||
845 ((flags & OPERAND_CONTROL) != (num & OPERAND_CONTROL)))
846 {
847 match=0;
848 break;
849 }
850 }
851
852 if (((flags & OPERAND_MINUS) && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
853 ((flags & OPERAND_PLUS) && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
854 ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
855 ((flags & OPERAND_ATPAR) && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
856 ((flags & OPERAND_ATSIGN) && ((X_op != O_absent) || (num != OPERAND_ATSIGN))))
857 {
858 match=0;
859 break;
860 }
861
862 }
863
864 /* we're only done if the operands matched AND there
865 are no more to check */
866 if (match && myops[i].X_op==0)
867 break;
868
869 next_opcode = (*opcode)+1;
870 if (next_opcode->opcode == 0)
871 break;
872 if (strcmp(next_opcode->name, (*opcode)->name))
873 break;
874 (*opcode) = next_opcode;
875 }
876 }
877
878 if (!match)
879 {
880 as_bad ("bad opcode or operands");
881 return (0);
882 }
883
884 /* Check that all registers that are required to be even are. */
885 /* Also, if any operands were marked as registers, but were really symbols */
886 /* fix that here. */
887 for (i=0; (*opcode)->operands[i]; i++)
888 {
889 if ((d10v_operands[(*opcode)->operands[i]].flags & OPERAND_EVEN) &&
890 (myops[i].X_add_number & 1))
891 as_fatal("Register number must be EVEN");
892 if (myops[i].X_op == O_register)
893 {
894 if (!(d10v_operands[(*opcode)->operands[i]].flags & OPERAND_REG))
895 {
896 myops[i].X_op = O_symbol;
897 myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
898 myops[i].X_add_number = 0;
899 myops[i].X_op_symbol = NULL;
900 /* FIXME create a fixup */
901 }
902 }
903 }
904
905 input_line_pointer = save;
906
907 /* at this point, we have "opcode" pointing to the opcode entry in the
908 d10v opcode table, with myops filled out with the operands. */
909 insn = build_insn ((*opcode), myops, 0);
910 /* printf("sub-insn = %lx\n",insn); */
911
912 return (insn);
913 }
914
915
916 /* if while processing a fixup, a reloc really needs to be created */
917 /* then it is done here */
918
919 arelent *
920 tc_gen_reloc (seg, fixp)
921 asection *seg;
922 fixS *fixp;
923 {
924 arelent *reloc;
925 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
926 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
927 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
928 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
929 if (reloc->howto == (reloc_howto_type *) NULL)
930 {
931 as_bad_where (fixp->fx_file, fixp->fx_line,
932 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
933 return NULL;
934 }
935 reloc->addend = fixp->fx_addnumber;
936 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
937 return reloc;
938 }
939
940 int
941 md_estimate_size_before_relax (fragp, seg)
942 fragS *fragp;
943 asection *seg;
944 {
945 abort ();
946 return 0;
947 }
948
949 long
950 md_pcrel_from_section (fixp, sec)
951 fixS *fixp;
952 segT sec;
953 {
954 return 0;
955 /* return fixp->fx_frag->fr_address + fixp->fx_where; */
956 }
957
958 int
959 md_apply_fix3 (fixp, valuep, seg)
960 fixS *fixp;
961 valueT *valuep;
962 segT seg;
963 {
964 char *where;
965 unsigned long insn;
966 long value;
967 int op_type;
968 int left=0;
969
970 if (fixp->fx_addsy == (symbolS *) NULL)
971 {
972 value = *valuep;
973 fixp->fx_done = 1;
974 }
975 else if (fixp->fx_pcrel)
976 value = *valuep;
977 else
978 {
979 value = fixp->fx_offset;
980 if (fixp->fx_subsy != (symbolS *) NULL)
981 {
982 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
983 value -= S_GET_VALUE (fixp->fx_subsy);
984 else
985 {
986 /* We don't actually support subtracting a symbol. */
987 as_bad_where (fixp->fx_file, fixp->fx_line,
988 "expression too complex");
989 }
990 }
991 }
992
993 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
994
995 op_type = fixp->fx_r_type;
996 if (op_type & 1024)
997 {
998 op_type -= 1024;
999 fixp->fx_r_type = BFD_RELOC_D10V_10_PCREL_L;
1000 left = 1;
1001 }
1002 else
1003 fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]);
1004
1005 /* Fetch the instruction, insert the fully resolved operand
1006 value, and stuff the instruction back again. */
1007 where = fixp->fx_frag->fr_literal + fixp->fx_where;
1008 insn = bfd_getb32 ((unsigned char *) where);
1009
1010 switch (fixp->fx_r_type)
1011 {
1012 case BFD_RELOC_D10V_10_PCREL_L:
1013 case BFD_RELOC_D10V_10_PCREL_R:
1014 case BFD_RELOC_D10V_18_PCREL:
1015 /* instruction addresses are always right-shifted by 2
1016 and pc-relative */
1017 if (!fixp->fx_pcrel)
1018 value -= fixp->fx_where;
1019 value >>= 2;
1020 default:
1021 break;
1022 }
1023 /* printf(" insn=%x value=%x where=%x pcrel=%x\n",insn,value,fixp->fx_where,fixp->fx_pcrel); */
1024
1025 insn = d10v_insert_operand (insn, op_type, (offsetT)value, left);
1026
1027 /* printf(" new insn=%x\n",insn); */
1028
1029 bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1030
1031 if (fixp->fx_done)
1032 return 1;
1033
1034 fixp->fx_addnumber = value;
1035 return 1;
1036 }
1037
1038
1039 /* d10v_cleanup() is called after the assembler has finished parsing the input
1040 file or after a label is defined. Because the D10V assembler sometimes saves short
1041 instructions to see if it can package them with the next instruction, there may
1042 be a short instruction that still needs written. */
1043 int
1044 d10v_cleanup (done)
1045 int done;
1046 {
1047 segT seg;
1048 subsegT subseg;
1049
1050 if ( prev_opcode && (done || (now_seg == prev_seg) && (now_subseg == prev_subseg)))
1051 {
1052 seg = now_seg;
1053 subseg = now_subseg;
1054 subseg_set (prev_seg, prev_subseg);
1055 write_1_short (prev_opcode, prev_insn, fixups);
1056 subseg_set (seg, subseg);
1057 prev_opcode = NULL;
1058 }
1059 return 1;
1060 }
This page took 0.050842 seconds and 4 git commands to generate.