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