Thu Jul 25 12:03:33 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 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 }