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