1fddef416Sniklas /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
2d2201f2fSdrahn    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
35f210c2aSfgsch    Free Software Foundation, Inc.
4fddef416Sniklas 
5fddef416Sniklas    This file is part of GAS, the GNU Assembler.
6fddef416Sniklas 
7fddef416Sniklas    GAS is free software; you can redistribute it and/or modify
8fddef416Sniklas    it under the terms of the GNU General Public License as published by
9fddef416Sniklas    the Free Software Foundation; either version 2, or (at your option)
10fddef416Sniklas    any later version.
11fddef416Sniklas 
12fddef416Sniklas    GAS is distributed in the hope that it will be useful,
13fddef416Sniklas    but WITHOUT ANY WARRANTY; without even the implied warranty of
14fddef416Sniklas    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15fddef416Sniklas    GNU General Public License for more details.
16fddef416Sniklas 
17fddef416Sniklas    You should have received a copy of the GNU General Public License
18fddef416Sniklas    along with GAS; see the file COPYING.  If not, write to
19fddef416Sniklas    the Free Software Foundation, 59 Temple Place - Suite 330,
20fddef416Sniklas    Boston, MA 02111-1307, USA.  */
21fddef416Sniklas 
22fddef416Sniklas #include <stdio.h>
23fddef416Sniklas #include "as.h"
24d2201f2fSdrahn #include "safe-ctype.h"
25fddef416Sniklas #include "subsegs.h"
26fddef416Sniklas #include "opcode/d10v.h"
27fddef416Sniklas #include "elf/ppc.h"
28fddef416Sniklas 
29fddef416Sniklas const char comment_chars[] = ";";
30fddef416Sniklas const char line_comment_chars[] = "#";
31fddef416Sniklas const char line_separator_chars[] = "";
32fddef416Sniklas const char *md_shortopts = "O";
33fddef416Sniklas const char EXP_CHARS[] = "eE";
34fddef416Sniklas const char FLT_CHARS[] = "dD";
35fddef416Sniklas 
36fddef416Sniklas int Optimizing = 0;
37fddef416Sniklas 
38f7cc78ecSespie #define AT_WORD_P(X) ((X)->X_op == O_right_shift \
39f7cc78ecSespie 		      && (X)->X_op_symbol != NULL \
40f7cc78ecSespie 		      && symbol_constant_p ((X)->X_op_symbol) \
41f7cc78ecSespie 		      && S_GET_VALUE ((X)->X_op_symbol) == AT_WORD_RIGHT_SHIFT)
42f7cc78ecSespie #define AT_WORD_RIGHT_SHIFT 2
43f7cc78ecSespie 
445f210c2aSfgsch /* Fixups.  */
45fddef416Sniklas #define MAX_INSN_FIXUPS (5)
46fddef416Sniklas struct d10v_fixup
47fddef416Sniklas {
48fddef416Sniklas   expressionS exp;
49fddef416Sniklas   int operand;
50fddef416Sniklas   int pcrel;
51fddef416Sniklas   int size;
52fddef416Sniklas   bfd_reloc_code_real_type reloc;
53fddef416Sniklas };
54fddef416Sniklas 
55fddef416Sniklas typedef struct _fixups
56fddef416Sniklas {
57fddef416Sniklas   int fc;
58fddef416Sniklas   struct d10v_fixup fix[MAX_INSN_FIXUPS];
59fddef416Sniklas   struct _fixups *next;
60fddef416Sniklas } Fixups;
61fddef416Sniklas 
62fddef416Sniklas static Fixups FixUps[2];
63fddef416Sniklas static Fixups *fixups;
64fddef416Sniklas 
65f7cc78ecSespie static int do_not_ignore_hash = 0;
66f7cc78ecSespie 
675f210c2aSfgsch typedef int packing_type;
685f210c2aSfgsch #define PACK_UNSPEC 	(0)	/* Packing order not specified.  */
695f210c2aSfgsch #define PACK_PARALLEL	(1)	/* "||"  */
705f210c2aSfgsch #define PACK_LEFT_RIGHT (2)	/* "->"  */
715f210c2aSfgsch #define PACK_RIGHT_LEFT (3)	/* "<-"  */
725f210c2aSfgsch static packing_type etype = PACK_UNSPEC; /* Used by d10v_cleanup.  */
73f7cc78ecSespie 
74d2201f2fSdrahn /* TRUE if instruction swapping warnings should be inhibited.
755f210c2aSfgsch    --nowarnswap.  */
76d2201f2fSdrahn static bfd_boolean flag_warn_suppress_instructionswap;
775f210c2aSfgsch 
78d2201f2fSdrahn /* TRUE if instruction packing should be performed when --gstabs is specified.
795f210c2aSfgsch    --gstabs-packing, --no-gstabs-packing.  */
80d2201f2fSdrahn static bfd_boolean flag_allow_gstabs_packing = 1;
815f210c2aSfgsch 
825f210c2aSfgsch /* Local functions.  */
83fddef416Sniklas static int reg_name_search PARAMS ((char *name));
84fddef416Sniklas static int register_name PARAMS ((expressionS *expressionP));
85fddef416Sniklas static int check_range PARAMS ((unsigned long num, int bits, int flags));
86fddef416Sniklas static int postfix PARAMS ((char *p));
87fddef416Sniklas static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
88fddef416Sniklas static int get_operands PARAMS ((expressionS exp[]));
89fddef416Sniklas static struct d10v_opcode *find_opcode PARAMS ((struct d10v_opcode *opcode, expressionS ops[]));
90fddef416Sniklas static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers, unsigned long insn));
915f210c2aSfgsch static void write_long PARAMS ((unsigned long insn, Fixups *fx));
92fddef416Sniklas static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
93fddef416Sniklas static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
945f210c2aSfgsch 				  struct d10v_opcode *opcode2, unsigned long insn2, packing_type exec_type, Fixups *fx));
95fddef416Sniklas static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
96fddef416Sniklas static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type,
97fddef416Sniklas 						   offsetT value, int left, fixS *fix));
98fddef416Sniklas static int parallel_ok PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
99fddef416Sniklas 				struct d10v_opcode *opcode2, unsigned long insn2,
1005f210c2aSfgsch 				packing_type exec_type));
101d2201f2fSdrahn 
102d2201f2fSdrahn static void check_resource_conflict PARAMS ((struct d10v_opcode *opcode1,
103d2201f2fSdrahn 					     unsigned long insn1,
104d2201f2fSdrahn 					     struct d10v_opcode *opcode2,
105d2201f2fSdrahn 					     unsigned long insn2));
106d2201f2fSdrahn 
107f7cc78ecSespie static symbolS * find_symbol_matching_register PARAMS ((expressionS *));
108fddef416Sniklas 
109f7cc78ecSespie struct option md_longopts[] =
110f7cc78ecSespie {
111f7cc78ecSespie #define OPTION_NOWARNSWAP (OPTION_MD_BASE)
112f7cc78ecSespie   {"nowarnswap", no_argument, NULL, OPTION_NOWARNSWAP},
1135f210c2aSfgsch #define OPTION_GSTABSPACKING (OPTION_MD_BASE + 1)
1145f210c2aSfgsch   {"gstabspacking",  no_argument, NULL, OPTION_GSTABSPACKING},
1155f210c2aSfgsch   {"gstabs-packing", no_argument, NULL, OPTION_GSTABSPACKING},
1165f210c2aSfgsch #define OPTION_NOGSTABSPACKING (OPTION_MD_BASE + 2)
1175f210c2aSfgsch   {"nogstabspacking",   no_argument, NULL, OPTION_NOGSTABSPACKING},
1185f210c2aSfgsch   {"no-gstabs-packing", no_argument, NULL, OPTION_NOGSTABSPACKING},
119fddef416Sniklas   {NULL, no_argument, NULL, 0}
120fddef416Sniklas };
1215f210c2aSfgsch 
122fddef416Sniklas size_t md_longopts_size = sizeof (md_longopts);
123fddef416Sniklas 
124fddef416Sniklas static void d10v_dot_word PARAMS ((int));
125fddef416Sniklas 
126fddef416Sniklas /* The target specific pseudo-ops which we support.  */
127fddef416Sniklas const pseudo_typeS md_pseudo_table[] =
128fddef416Sniklas {
129fddef416Sniklas   { "word",	d10v_dot_word,	2 },
130fddef416Sniklas   { NULL,       NULL,           0 }
131fddef416Sniklas };
132fddef416Sniklas 
133fddef416Sniklas /* Opcode hash table.  */
134fddef416Sniklas static struct hash_control *d10v_hash;
135fddef416Sniklas 
1365f210c2aSfgsch /* Do a binary search of the d10v_predefined_registers array to see if
1375f210c2aSfgsch    NAME is a valid regiter name.  Return the register number from the
1385f210c2aSfgsch    array on success, or -1 on failure.  */
139fddef416Sniklas 
140fddef416Sniklas static int
reg_name_search(name)141fddef416Sniklas reg_name_search (name)
142fddef416Sniklas      char *name;
143fddef416Sniklas {
144fddef416Sniklas   int middle, low, high;
145fddef416Sniklas   int cmp;
146fddef416Sniklas 
147fddef416Sniklas   low = 0;
148fddef416Sniklas   high = d10v_reg_name_cnt () - 1;
149fddef416Sniklas 
150fddef416Sniklas   do
151fddef416Sniklas     {
152fddef416Sniklas       middle = (low + high) / 2;
153fddef416Sniklas       cmp = strcasecmp (name, d10v_predefined_registers[middle].name);
154fddef416Sniklas       if (cmp < 0)
155fddef416Sniklas 	high = middle - 1;
156fddef416Sniklas       else if (cmp > 0)
157fddef416Sniklas 	low = middle + 1;
158fddef416Sniklas       else
159fddef416Sniklas 	return d10v_predefined_registers[middle].value;
160fddef416Sniklas     }
161fddef416Sniklas   while (low <= high);
162fddef416Sniklas   return -1;
163fddef416Sniklas }
164fddef416Sniklas 
1655f210c2aSfgsch /* Check the string at input_line_pointer
1665f210c2aSfgsch    to see if it is a valid register name.  */
167fddef416Sniklas 
168fddef416Sniklas static int
register_name(expressionP)169fddef416Sniklas register_name (expressionP)
170fddef416Sniklas      expressionS *expressionP;
171fddef416Sniklas {
172fddef416Sniklas   int reg_number;
173fddef416Sniklas   char c, *p = input_line_pointer;
174fddef416Sniklas 
1755f210c2aSfgsch   while (*p
1765f210c2aSfgsch 	 && *p != '\n' && *p != '\r' && *p != ',' && *p != ' ' && *p != ')')
177fddef416Sniklas     p++;
178fddef416Sniklas 
179fddef416Sniklas   c = *p;
180fddef416Sniklas   if (c)
181fddef416Sniklas     *p++ = 0;
182fddef416Sniklas 
1835f210c2aSfgsch   /* Look to see if it's in the register table.  */
184fddef416Sniklas   reg_number = reg_name_search (input_line_pointer);
185fddef416Sniklas   if (reg_number >= 0)
186fddef416Sniklas     {
187fddef416Sniklas       expressionP->X_op = O_register;
1885f210c2aSfgsch       /* Temporarily store a pointer to the string here.  */
189f7cc78ecSespie       expressionP->X_op_symbol = (symbolS *) input_line_pointer;
190fddef416Sniklas       expressionP->X_add_number = reg_number;
191fddef416Sniklas       input_line_pointer = p;
192fddef416Sniklas       return 1;
193fddef416Sniklas     }
194fddef416Sniklas   if (c)
195fddef416Sniklas     *(p - 1) = c;
196fddef416Sniklas   return 0;
197fddef416Sniklas }
198fddef416Sniklas 
199fddef416Sniklas static int
check_range(num,bits,flags)200fddef416Sniklas check_range (num, bits, flags)
201fddef416Sniklas      unsigned long num;
202fddef416Sniklas      int bits;
203fddef416Sniklas      int flags;
204fddef416Sniklas {
2055f210c2aSfgsch   long min, max;
206fddef416Sniklas   int retval = 0;
207fddef416Sniklas 
2085f210c2aSfgsch   /* Don't bother checking 16-bit values.  */
209fddef416Sniklas   if (bits == 16)
210fddef416Sniklas     return 0;
211fddef416Sniklas 
212fddef416Sniklas   if (flags & OPERAND_SHIFT)
213fddef416Sniklas     {
2145f210c2aSfgsch       /* All special shift operands are unsigned and <= 16.
2155f210c2aSfgsch 	 We allow 0 for now.  */
216fddef416Sniklas       if (num > 16)
217fddef416Sniklas 	return 1;
218fddef416Sniklas       else
219fddef416Sniklas 	return 0;
220fddef416Sniklas     }
221fddef416Sniklas 
222fddef416Sniklas   if (flags & OPERAND_SIGNED)
223fddef416Sniklas     {
2245f210c2aSfgsch       /* Signed 3-bit integers are restricted to the (-2, 3) range.  */
225f7cc78ecSespie       if (flags & RESTRICTED_NUM3)
226f7cc78ecSespie 	{
227f7cc78ecSespie 	  if ((long) num < -2 || (long) num > 3)
228f7cc78ecSespie 	    retval = 1;
229f7cc78ecSespie 	}
230f7cc78ecSespie       else
231f7cc78ecSespie 	{
232fddef416Sniklas 	  max = (1 << (bits - 1)) - 1;
233fddef416Sniklas 	  min = - (1 << (bits - 1));
234fddef416Sniklas 	  if (((long) num > max) || ((long) num < min))
235fddef416Sniklas 	    retval = 1;
236fddef416Sniklas 	}
237f7cc78ecSespie     }
238fddef416Sniklas   else
239fddef416Sniklas     {
240fddef416Sniklas       max = (1 << bits) - 1;
241fddef416Sniklas       min = 0;
2425f210c2aSfgsch       if (((long) num > max) || ((long) num < min))
243fddef416Sniklas 	retval = 1;
244fddef416Sniklas     }
245fddef416Sniklas   return retval;
246fddef416Sniklas }
247fddef416Sniklas 
248fddef416Sniklas void
md_show_usage(stream)249fddef416Sniklas md_show_usage (stream)
250fddef416Sniklas      FILE *stream;
251fddef416Sniklas {
252f7cc78ecSespie   fprintf (stream, _("D10V options:\n\
2535f210c2aSfgsch -O                      Optimize.  Will do some operations in parallel.\n\
2545f210c2aSfgsch --gstabs-packing        Pack adjacent short instructions together even\n\
2555f210c2aSfgsch                         when --gstabs is specified.  On by default.\n\
2565f210c2aSfgsch --no-gstabs-packing     If --gstabs is specified, do not pack adjacent\n\
2575f210c2aSfgsch                         instructions together.\n"));
258fddef416Sniklas }
259fddef416Sniklas 
260fddef416Sniklas int
md_parse_option(c,arg)261fddef416Sniklas md_parse_option (c, arg)
262fddef416Sniklas      int c;
2635f210c2aSfgsch      char *arg ATTRIBUTE_UNUSED;
264fddef416Sniklas {
265fddef416Sniklas   switch (c)
266fddef416Sniklas     {
267fddef416Sniklas     case 'O':
2685f210c2aSfgsch       /* Optimize. Will attempt to parallelize operations.  */
269fddef416Sniklas       Optimizing = 1;
270fddef416Sniklas       break;
271f7cc78ecSespie     case OPTION_NOWARNSWAP:
272f7cc78ecSespie       flag_warn_suppress_instructionswap = 1;
273f7cc78ecSespie       break;
2745f210c2aSfgsch     case OPTION_GSTABSPACKING:
2755f210c2aSfgsch       flag_allow_gstabs_packing = 1;
2765f210c2aSfgsch       break;
2775f210c2aSfgsch     case OPTION_NOGSTABSPACKING:
2785f210c2aSfgsch       flag_allow_gstabs_packing = 0;
2795f210c2aSfgsch       break;
280fddef416Sniklas     default:
281fddef416Sniklas       return 0;
282fddef416Sniklas     }
283fddef416Sniklas   return 1;
284fddef416Sniklas }
285fddef416Sniklas 
286fddef416Sniklas symbolS *
md_undefined_symbol(name)287fddef416Sniklas md_undefined_symbol (name)
2885f210c2aSfgsch      char *name ATTRIBUTE_UNUSED;
289fddef416Sniklas {
290fddef416Sniklas   return 0;
291fddef416Sniklas }
292fddef416Sniklas 
2935f210c2aSfgsch /* Turn a string in input_line_pointer into a floating point constant
2945f210c2aSfgsch    of type TYPE, and store the appropriate bytes in *LITP.  The number
2955f210c2aSfgsch    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
2965f210c2aSfgsch    returned, or NULL on OK.  */
2975f210c2aSfgsch 
298fddef416Sniklas char *
md_atof(type,litP,sizeP)299fddef416Sniklas md_atof (type, litP, sizeP)
300fddef416Sniklas      int type;
301fddef416Sniklas      char *litP;
302fddef416Sniklas      int *sizeP;
303fddef416Sniklas {
304fddef416Sniklas   int prec;
305fddef416Sniklas   LITTLENUM_TYPE words[4];
306fddef416Sniklas   char *t;
307fddef416Sniklas   int i;
308fddef416Sniklas 
309fddef416Sniklas   switch (type)
310fddef416Sniklas     {
311fddef416Sniklas     case 'f':
312fddef416Sniklas       prec = 2;
313fddef416Sniklas       break;
314fddef416Sniklas     case 'd':
315fddef416Sniklas       prec = 4;
316fddef416Sniklas       break;
317fddef416Sniklas     default:
318fddef416Sniklas       *sizeP = 0;
319f7cc78ecSespie       return _("bad call to md_atof");
320fddef416Sniklas     }
321fddef416Sniklas 
322fddef416Sniklas   t = atof_ieee (input_line_pointer, type, words);
323fddef416Sniklas   if (t)
324fddef416Sniklas     input_line_pointer = t;
325fddef416Sniklas 
326fddef416Sniklas   *sizeP = prec * 2;
327fddef416Sniklas 
328fddef416Sniklas   for (i = 0; i < prec; i++)
329fddef416Sniklas     {
330fddef416Sniklas       md_number_to_chars (litP, (valueT) words[i], 2);
331fddef416Sniklas       litP += 2;
332fddef416Sniklas     }
333fddef416Sniklas   return NULL;
334fddef416Sniklas }
335fddef416Sniklas 
336fddef416Sniklas void
md_convert_frag(abfd,sec,fragP)337fddef416Sniklas md_convert_frag (abfd, sec, fragP)
3385f210c2aSfgsch      bfd *abfd ATTRIBUTE_UNUSED;
3395f210c2aSfgsch      asection *sec ATTRIBUTE_UNUSED;
3405f210c2aSfgsch      fragS *fragP ATTRIBUTE_UNUSED;
341fddef416Sniklas {
342fddef416Sniklas   abort ();
343fddef416Sniklas }
344fddef416Sniklas 
345fddef416Sniklas valueT
md_section_align(seg,addr)346fddef416Sniklas md_section_align (seg, addr)
347fddef416Sniklas      asection *seg;
348fddef416Sniklas      valueT addr;
349fddef416Sniklas {
350fddef416Sniklas   int align = bfd_get_section_alignment (stdoutput, seg);
351fddef416Sniklas   return ((addr + (1 << align) - 1) & (-1 << align));
352fddef416Sniklas }
353fddef416Sniklas 
354fddef416Sniklas void
md_begin()355fddef416Sniklas md_begin ()
356fddef416Sniklas {
357fddef416Sniklas   char *prev_name = "";
358fddef416Sniklas   struct d10v_opcode *opcode;
359fddef416Sniklas   d10v_hash = hash_new ();
360fddef416Sniklas 
361fddef416Sniklas   /* Insert unique names into hash table.  The D10v instruction set
362fddef416Sniklas      has many identical opcode names that have different opcodes based
363fddef416Sniklas      on the operands.  This hash table then provides a quick index to
364fddef416Sniklas      the first opcode with a particular name in the opcode table.  */
365fddef416Sniklas 
366fddef416Sniklas   for (opcode = (struct d10v_opcode *) d10v_opcodes; opcode->name; opcode++)
367fddef416Sniklas     {
368fddef416Sniklas       if (strcmp (prev_name, opcode->name))
369fddef416Sniklas 	{
370fddef416Sniklas 	  prev_name = (char *) opcode->name;
371fddef416Sniklas 	  hash_insert (d10v_hash, opcode->name, (char *) opcode);
372fddef416Sniklas 	}
373fddef416Sniklas     }
374fddef416Sniklas 
375fddef416Sniklas   fixups = &FixUps[0];
376fddef416Sniklas   FixUps[0].next = &FixUps[1];
377fddef416Sniklas   FixUps[1].next = &FixUps[0];
378fddef416Sniklas }
379fddef416Sniklas 
3805f210c2aSfgsch /* Remove the postincrement or postdecrement operator ( '+' or '-' )
3815f210c2aSfgsch    from an expression.  */
382fddef416Sniklas 
3835f210c2aSfgsch static int
postfix(p)3845f210c2aSfgsch postfix (p)
385fddef416Sniklas      char *p;
386fddef416Sniklas {
387fddef416Sniklas   while (*p != '-' && *p != '+')
388fddef416Sniklas     {
389fddef416Sniklas       if (*p == 0 || *p == '\n' || *p == '\r')
390fddef416Sniklas 	break;
391fddef416Sniklas       p++;
392fddef416Sniklas     }
393fddef416Sniklas 
394fddef416Sniklas   if (*p == '-')
395fddef416Sniklas     {
396fddef416Sniklas       *p = ' ';
397fddef416Sniklas       return (-1);
398fddef416Sniklas     }
399fddef416Sniklas   if (*p == '+')
400fddef416Sniklas     {
401fddef416Sniklas       *p = ' ';
402fddef416Sniklas       return (1);
403fddef416Sniklas     }
404fddef416Sniklas 
405fddef416Sniklas   return (0);
406fddef416Sniklas }
407fddef416Sniklas 
408fddef416Sniklas static bfd_reloc_code_real_type
get_reloc(op)409fddef416Sniklas get_reloc (op)
410fddef416Sniklas      struct d10v_operand *op;
411fddef416Sniklas {
412fddef416Sniklas   int bits = op->bits;
413fddef416Sniklas 
414fddef416Sniklas   if (bits <= 4)
415fddef416Sniklas     return (0);
416fddef416Sniklas 
417fddef416Sniklas   if (op->flags & OPERAND_ADDR)
418fddef416Sniklas     {
419fddef416Sniklas       if (bits == 8)
420fddef416Sniklas 	return (BFD_RELOC_D10V_10_PCREL_R);
421fddef416Sniklas       else
422fddef416Sniklas 	return (BFD_RELOC_D10V_18_PCREL);
423fddef416Sniklas     }
424fddef416Sniklas 
425fddef416Sniklas   return (BFD_RELOC_16);
426fddef416Sniklas }
427fddef416Sniklas 
4285f210c2aSfgsch /* Parse a string of operands.  Return an array of expressions.  */
429fddef416Sniklas 
430fddef416Sniklas static int
get_operands(exp)431fddef416Sniklas get_operands (exp)
432fddef416Sniklas      expressionS exp[];
433fddef416Sniklas {
434fddef416Sniklas   char *p = input_line_pointer;
435fddef416Sniklas   int numops = 0;
436fddef416Sniklas   int post = 0;
437f7cc78ecSespie   int uses_at = 0;
438fddef416Sniklas 
439fddef416Sniklas   while (*p)
440fddef416Sniklas     {
441fddef416Sniklas       while (*p == ' ' || *p == '\t' || *p == ',')
442fddef416Sniklas 	p++;
443fddef416Sniklas       if (*p == 0 || *p == '\n' || *p == '\r')
444fddef416Sniklas 	break;
445fddef416Sniklas 
446fddef416Sniklas       if (*p == '@')
447fddef416Sniklas 	{
448f7cc78ecSespie 	  uses_at = 1;
449f7cc78ecSespie 
450fddef416Sniklas 	  p++;
451fddef416Sniklas 	  exp[numops].X_op = O_absent;
452fddef416Sniklas 	  if (*p == '(')
453fddef416Sniklas 	    {
454fddef416Sniklas 	      p++;
455fddef416Sniklas 	      exp[numops].X_add_number = OPERAND_ATPAR;
456fddef416Sniklas 	    }
457fddef416Sniklas 	  else if (*p == '-')
458fddef416Sniklas 	    {
459fddef416Sniklas 	      p++;
460fddef416Sniklas 	      exp[numops].X_add_number = OPERAND_ATMINUS;
461fddef416Sniklas 	    }
462fddef416Sniklas 	  else
463fddef416Sniklas 	    {
464fddef416Sniklas 	      exp[numops].X_add_number = OPERAND_ATSIGN;
465d2201f2fSdrahn 	      if (*p == '+')
466d2201f2fSdrahn 		{
467d2201f2fSdrahn 		  numops++;
468d2201f2fSdrahn 		  exp[numops].X_op = O_absent;
469d2201f2fSdrahn 		  exp[numops].X_add_number = OPERAND_PLUS;
470d2201f2fSdrahn 		  p++;
471d2201f2fSdrahn 		}
472fddef416Sniklas 	      post = postfix (p);
473fddef416Sniklas 	    }
474fddef416Sniklas 	  numops++;
475fddef416Sniklas 	  continue;
476fddef416Sniklas 	}
477fddef416Sniklas 
478fddef416Sniklas       if (*p == ')')
479fddef416Sniklas 	{
4805f210c2aSfgsch 	  /* Just skip the trailing paren.  */
481fddef416Sniklas 	  p++;
482fddef416Sniklas 	  continue;
483fddef416Sniklas 	}
484fddef416Sniklas 
485fddef416Sniklas       input_line_pointer = p;
486fddef416Sniklas 
4875f210c2aSfgsch       /* Check to see if it might be a register name.  */
488fddef416Sniklas       if (!register_name (&exp[numops]))
489fddef416Sniklas 	{
4905f210c2aSfgsch 	  /* Parse as an expression.  */
491f7cc78ecSespie 	  if (uses_at)
492f7cc78ecSespie 	    {
493f7cc78ecSespie 	      /* Any expression that involves the indirect addressing
494f7cc78ecSespie 		 cannot also involve immediate addressing.  Therefore
495f7cc78ecSespie 		 the use of the hash character is illegal.  */
496f7cc78ecSespie 	      int save = do_not_ignore_hash;
497f7cc78ecSespie 	      do_not_ignore_hash = 1;
498f7cc78ecSespie 
499f7cc78ecSespie 	      expression (&exp[numops]);
500f7cc78ecSespie 
501f7cc78ecSespie 	      do_not_ignore_hash = save;
502f7cc78ecSespie 	    }
503f7cc78ecSespie 	  else
504fddef416Sniklas 	    expression (&exp[numops]);
505fddef416Sniklas 	}
506fddef416Sniklas 
507f7cc78ecSespie       if (strncasecmp (input_line_pointer, "@word", 5) == 0)
508fddef416Sniklas 	{
509f7cc78ecSespie 	  input_line_pointer += 5;
510fddef416Sniklas 	  if (exp[numops].X_op == O_register)
511fddef416Sniklas 	    {
5125f210c2aSfgsch 	      /* If it looked like a register name but was followed by
513f7cc78ecSespie                  "@word" then it was really a symbol, so change it to
5145f210c2aSfgsch                  one.  */
515fddef416Sniklas 	      exp[numops].X_op = O_symbol;
5165f210c2aSfgsch 	      exp[numops].X_add_symbol =
5175f210c2aSfgsch 		symbol_find_or_make ((char *) exp[numops].X_op_symbol);
518fddef416Sniklas 	    }
519f7cc78ecSespie 
5205f210c2aSfgsch 	  /* Check for identifier@word+constant.  */
521f7cc78ecSespie 	  if (*input_line_pointer == '-' || *input_line_pointer == '+')
522f7cc78ecSespie 	    {
523f7cc78ecSespie 	      expressionS new_exp;
524f7cc78ecSespie 	      expression (&new_exp);
525f7cc78ecSespie 	      exp[numops].X_add_number = new_exp.X_add_number;
526f7cc78ecSespie 	    }
527f7cc78ecSespie 
5285f210c2aSfgsch 	  /* Convert expr into a right shift by AT_WORD_RIGHT_SHIFT.  */
529f7cc78ecSespie 	  {
530f7cc78ecSespie 	    expressionS new_exp;
531f7cc78ecSespie 	    memset (&new_exp, 0, sizeof new_exp);
532f7cc78ecSespie 	    new_exp.X_add_number = AT_WORD_RIGHT_SHIFT;
533f7cc78ecSespie 	    new_exp.X_op = O_constant;
534f7cc78ecSespie 	    new_exp.X_unsigned = 1;
535f7cc78ecSespie 	    exp[numops].X_op_symbol = make_expr_symbol (&new_exp);
536f7cc78ecSespie 	    exp[numops].X_op = O_right_shift;
537f7cc78ecSespie 	  }
538f7cc78ecSespie 
539f7cc78ecSespie 	  know (AT_WORD_P (&exp[numops]));
540fddef416Sniklas 	}
541fddef416Sniklas 
542fddef416Sniklas       if (exp[numops].X_op == O_illegal)
543f7cc78ecSespie 	as_bad (_("illegal operand"));
544fddef416Sniklas       else if (exp[numops].X_op == O_absent)
545f7cc78ecSespie 	as_bad (_("missing operand"));
546fddef416Sniklas 
547fddef416Sniklas       numops++;
548fddef416Sniklas       p = input_line_pointer;
549fddef416Sniklas     }
550fddef416Sniklas 
551fddef416Sniklas   switch (post)
552fddef416Sniklas     {
5535f210c2aSfgsch     case -1:	/* Postdecrement mode.  */
554fddef416Sniklas       exp[numops].X_op = O_absent;
555fddef416Sniklas       exp[numops++].X_add_number = OPERAND_MINUS;
556fddef416Sniklas       break;
5575f210c2aSfgsch     case 1:	/* Postincrement mode.  */
558fddef416Sniklas       exp[numops].X_op = O_absent;
559fddef416Sniklas       exp[numops++].X_add_number = OPERAND_PLUS;
560fddef416Sniklas       break;
561fddef416Sniklas     }
562fddef416Sniklas 
563fddef416Sniklas   exp[numops].X_op = 0;
564fddef416Sniklas   return (numops);
565fddef416Sniklas }
566fddef416Sniklas 
567fddef416Sniklas static unsigned long
d10v_insert_operand(insn,op_type,value,left,fix)568fddef416Sniklas d10v_insert_operand (insn, op_type, value, left, fix)
569fddef416Sniklas      unsigned long insn;
570fddef416Sniklas      int op_type;
571fddef416Sniklas      offsetT value;
572fddef416Sniklas      int left;
573fddef416Sniklas      fixS *fix;
574fddef416Sniklas {
575fddef416Sniklas   int shift, bits;
576fddef416Sniklas 
577fddef416Sniklas   shift = d10v_operands[op_type].shift;
578fddef416Sniklas   if (left)
579fddef416Sniklas     shift += 15;
580fddef416Sniklas 
581fddef416Sniklas   bits = d10v_operands[op_type].bits;
582fddef416Sniklas 
5835f210c2aSfgsch   /* Truncate to the proper number of bits.  */
584fddef416Sniklas   if (check_range (value, bits, d10v_operands[op_type].flags))
5855f210c2aSfgsch     as_bad_where (fix->fx_file, fix->fx_line,
586d2201f2fSdrahn 		  _("operand out of range: %ld"), (long) value);
587fddef416Sniklas 
588fddef416Sniklas   value &= 0x7FFFFFFF >> (31 - bits);
589fddef416Sniklas   insn |= (value << shift);
590fddef416Sniklas 
591fddef416Sniklas   return insn;
592fddef416Sniklas }
593fddef416Sniklas 
5945f210c2aSfgsch /* Take a pointer to the opcode entry in the opcode table and the
5955f210c2aSfgsch    array of operand expressions.  Return the instruction.  */
596fddef416Sniklas 
597fddef416Sniklas static unsigned long
build_insn(opcode,opers,insn)598fddef416Sniklas build_insn (opcode, opers, insn)
599fddef416Sniklas      struct d10v_opcode *opcode;
600fddef416Sniklas      expressionS *opers;
601fddef416Sniklas      unsigned long insn;
602fddef416Sniklas {
603fddef416Sniklas   int i, bits, shift, flags, format;
604f7cc78ecSespie   unsigned long number;
605fddef416Sniklas 
6065f210c2aSfgsch   /* The insn argument is only used for the DIVS kludge.  */
607fddef416Sniklas   if (insn)
608fddef416Sniklas     format = LONG_R;
609fddef416Sniklas   else
610fddef416Sniklas     {
611fddef416Sniklas       insn = opcode->opcode;
612fddef416Sniklas       format = opcode->format;
613fddef416Sniklas     }
614fddef416Sniklas 
615fddef416Sniklas   for (i = 0; opcode->operands[i]; i++)
616fddef416Sniklas     {
617fddef416Sniklas       flags = d10v_operands[opcode->operands[i]].flags;
618fddef416Sniklas       bits = d10v_operands[opcode->operands[i]].bits;
619fddef416Sniklas       shift = d10v_operands[opcode->operands[i]].shift;
620fddef416Sniklas       number = opers[i].X_add_number;
621fddef416Sniklas 
622fddef416Sniklas       if (flags & OPERAND_REG)
623fddef416Sniklas 	{
624fddef416Sniklas 	  number &= REGISTER_MASK;
625fddef416Sniklas 	  if (format == LONG_L)
626fddef416Sniklas 	    shift += 15;
627fddef416Sniklas 	}
628fddef416Sniklas 
629fddef416Sniklas       if (opers[i].X_op != O_register && opers[i].X_op != O_constant)
630fddef416Sniklas 	{
6315f210c2aSfgsch 	  /* Now create a fixup.  */
632fddef416Sniklas 
633fddef416Sniklas 	  if (fixups->fc >= MAX_INSN_FIXUPS)
634f7cc78ecSespie 	    as_fatal (_("too many fixups"));
635fddef416Sniklas 
636f7cc78ecSespie 	  if (AT_WORD_P (&opers[i]))
637fddef416Sniklas 	    {
638*cf2f2c56Smiod 	      /* Recognize XXX>>1+N aka XXX@word+N as special (AT_WORD).  */
639fddef416Sniklas 	      fixups->fix[fixups->fc].reloc = BFD_RELOC_D10V_18;
640f7cc78ecSespie 	      opers[i].X_op = O_symbol;
6415f210c2aSfgsch 	      opers[i].X_op_symbol = NULL; /* Should free it.  */
642f7cc78ecSespie 	      /* number is left shifted by AT_WORD_RIGHT_SHIFT so
643f7cc78ecSespie                  that, it is aligned with the symbol's value.  Later,
644f7cc78ecSespie                  BFD_RELOC_D10V_18 will right shift (symbol_value +
645f7cc78ecSespie                  X_add_number).  */
646f7cc78ecSespie 	      number <<= AT_WORD_RIGHT_SHIFT;
647f7cc78ecSespie 	      opers[i].X_add_number = number;
648f7cc78ecSespie 	    }
649f7cc78ecSespie 	  else
650d2201f2fSdrahn 	    {
651fddef416Sniklas 	      fixups->fix[fixups->fc].reloc =
652fddef416Sniklas 		get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
653fddef416Sniklas 
654d2201f2fSdrahn 	      /* Check that an immediate was passed to ops that expect one.  */
655d2201f2fSdrahn 	      if ((flags & OPERAND_NUM)
656d2201f2fSdrahn 		  && (fixups->fix[fixups->fc].reloc == 0))
657d2201f2fSdrahn 		as_bad (_("operand is not an immediate"));
658d2201f2fSdrahn 	    }
659d2201f2fSdrahn 
660fddef416Sniklas 	  if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
661fddef416Sniklas 	      fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
662fddef416Sniklas 	    fixups->fix[fixups->fc].size = 2;
663fddef416Sniklas 	  else
664fddef416Sniklas 	    fixups->fix[fixups->fc].size = 4;
665fddef416Sniklas 
666fddef416Sniklas 	  fixups->fix[fixups->fc].exp = opers[i];
667fddef416Sniklas 	  fixups->fix[fixups->fc].operand = opcode->operands[i];
6685f210c2aSfgsch 	  fixups->fix[fixups->fc].pcrel =
669d2201f2fSdrahn 	    (flags & OPERAND_ADDR) ? TRUE : FALSE;
670fddef416Sniklas 	  (fixups->fc)++;
671fddef416Sniklas 	}
672fddef416Sniklas 
6735f210c2aSfgsch       /* Truncate to the proper number of bits.  */
674fddef416Sniklas       if ((opers[i].X_op == O_constant) && check_range (number, bits, flags))
675d2201f2fSdrahn 	as_bad (_("operand out of range: %lu"), number);
676fddef416Sniklas       number &= 0x7FFFFFFF >> (31 - bits);
677fddef416Sniklas       insn = insn | (number << shift);
678fddef416Sniklas     }
679fddef416Sniklas 
680d2201f2fSdrahn   /* kludge: for DIVS, we need to put the operands in twice on the second
681d2201f2fSdrahn      pass, format is changed to LONG_R to force the second set of operands
682d2201f2fSdrahn      to not be shifted over 15.  */
683fddef416Sniklas   if ((opcode->opcode == OPCODE_DIVS) && (format == LONG_L))
684fddef416Sniklas     insn = build_insn (opcode, opers, insn);
685fddef416Sniklas 
686fddef416Sniklas   return insn;
687fddef416Sniklas }
688fddef416Sniklas 
6895f210c2aSfgsch /* Write out a long form instruction.  */
6905f210c2aSfgsch 
691fddef416Sniklas static void
write_long(insn,fx)6925f210c2aSfgsch write_long (insn, fx)
693fddef416Sniklas      unsigned long insn;
694fddef416Sniklas      Fixups *fx;
695fddef416Sniklas {
696fddef416Sniklas   int i, where;
697fddef416Sniklas   char *f = frag_more (4);
698fddef416Sniklas 
699fddef416Sniklas   insn |= FM11;
700fddef416Sniklas   number_to_chars_bigendian (f, insn, 4);
701fddef416Sniklas 
702fddef416Sniklas   for (i = 0; i < fx->fc; i++)
703fddef416Sniklas     {
704fddef416Sniklas       if (fx->fix[i].reloc)
705fddef416Sniklas 	{
706fddef416Sniklas 	  where = f - frag_now->fr_literal;
707fddef416Sniklas 	  if (fx->fix[i].size == 2)
708fddef416Sniklas 	    where += 2;
709fddef416Sniklas 
710fddef416Sniklas 	  if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
711fddef416Sniklas 	    fx->fix[i].operand |= 4096;
712fddef416Sniklas 
713fddef416Sniklas 	  fix_new_exp (frag_now,
714fddef416Sniklas 		       where,
715fddef416Sniklas 		       fx->fix[i].size,
716fddef416Sniklas 		       &(fx->fix[i].exp),
717fddef416Sniklas 		       fx->fix[i].pcrel,
718fddef416Sniklas 		       fx->fix[i].operand|2048);
719fddef416Sniklas 	}
720fddef416Sniklas     }
721fddef416Sniklas   fx->fc = 0;
722fddef416Sniklas }
723fddef416Sniklas 
7245f210c2aSfgsch /* Write out a short form instruction by itself.  */
725fddef416Sniklas 
726fddef416Sniklas static void
write_1_short(opcode,insn,fx)727fddef416Sniklas write_1_short (opcode, insn, fx)
728fddef416Sniklas      struct d10v_opcode *opcode;
729fddef416Sniklas      unsigned long insn;
730fddef416Sniklas      Fixups *fx;
731fddef416Sniklas {
732fddef416Sniklas   char *f = frag_more (4);
733fddef416Sniklas   int i, where;
734fddef416Sniklas 
735fddef416Sniklas   if (opcode->exec_type & PARONLY)
736f7cc78ecSespie     as_fatal (_("Instruction must be executed in parallel with another instruction."));
737fddef416Sniklas 
738d2201f2fSdrahn   /* The other container needs to be NOP.
739d2201f2fSdrahn      According to 4.3.1: for FM=00, sub-instructions performed only by IU
740d2201f2fSdrahn      cannot be encoded in L-container.  */
741fddef416Sniklas   if (opcode->unit == IU)
7425f210c2aSfgsch     insn |= FM00 | (NOP << 15);		/* Right container.  */
743fddef416Sniklas   else
7445f210c2aSfgsch     insn = FM00 | (insn << 15) | NOP;	/* Left container.  */
745fddef416Sniklas 
746fddef416Sniklas   number_to_chars_bigendian (f, insn, 4);
747fddef416Sniklas   for (i = 0; i < fx->fc; i++)
748fddef416Sniklas     {
749fddef416Sniklas       if (fx->fix[i].reloc)
750fddef416Sniklas 	{
751fddef416Sniklas 	  where = f - frag_now->fr_literal;
752fddef416Sniklas 	  if (fx->fix[i].size == 2)
753fddef416Sniklas 	    where += 2;
754fddef416Sniklas 
755fddef416Sniklas 	  if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
756fddef416Sniklas 	    fx->fix[i].operand |= 4096;
757fddef416Sniklas 
7585f210c2aSfgsch 	  /* If it's an R reloc, we may have to switch it to L.  */
7595f210c2aSfgsch 	  if ((fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R)
7605f210c2aSfgsch 	      && (opcode->unit != IU))
761fddef416Sniklas 	    fx->fix[i].operand |= 1024;
762fddef416Sniklas 
763fddef416Sniklas 	  fix_new_exp (frag_now,
764fddef416Sniklas 		       where,
765fddef416Sniklas 		       fx->fix[i].size,
766fddef416Sniklas 		       &(fx->fix[i].exp),
767fddef416Sniklas 		       fx->fix[i].pcrel,
768fddef416Sniklas 		       fx->fix[i].operand|2048);
769fddef416Sniklas 	}
770fddef416Sniklas     }
771fddef416Sniklas   fx->fc = 0;
772fddef416Sniklas }
773fddef416Sniklas 
7745f210c2aSfgsch /* Expects two short instructions.
7755f210c2aSfgsch    If possible, writes out both as a single packed instruction.
7765f210c2aSfgsch    Otherwise, writes out the first one, packed with a NOP.
7775f210c2aSfgsch    Returns number of instructions not written out.  */
7785f210c2aSfgsch 
779fddef416Sniklas static int
write_2_short(opcode1,insn1,opcode2,insn2,exec_type,fx)780fddef416Sniklas write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
781fddef416Sniklas      struct d10v_opcode *opcode1, *opcode2;
782fddef416Sniklas      unsigned long insn1, insn2;
7835f210c2aSfgsch      packing_type exec_type;
784fddef416Sniklas      Fixups *fx;
785fddef416Sniklas {
786fddef416Sniklas   unsigned long insn;
787fddef416Sniklas   char *f;
788fddef416Sniklas   int i, j, where;
789fddef416Sniklas 
7905f210c2aSfgsch   if ((exec_type != PACK_PARALLEL)
7915f210c2aSfgsch       && ((opcode1->exec_type & PARONLY) || (opcode2->exec_type & PARONLY)))
792f7cc78ecSespie     as_fatal (_("Instruction must be executed in parallel"));
793fddef416Sniklas 
794fddef416Sniklas   if ((opcode1->format & LONG_OPCODE) || (opcode2->format & LONG_OPCODE))
795f7cc78ecSespie     as_fatal (_("Long instructions may not be combined."));
796fddef416Sniklas 
797fddef416Sniklas   switch (exec_type)
798fddef416Sniklas     {
7995f210c2aSfgsch     case PACK_UNSPEC:	/* Order not specified.  */
8005f210c2aSfgsch       if (opcode1->exec_type & ALONE)
801fddef416Sniklas 	{
802d2201f2fSdrahn 	  /* Case of a short branch on a separate GAS line.  Pack with NOP.  */
8035f210c2aSfgsch 	  write_1_short (opcode1, insn1, fx->next);
8045f210c2aSfgsch 	  return 1;
8055f210c2aSfgsch 	}
8065f210c2aSfgsch       if (Optimizing
8075f210c2aSfgsch 	  && parallel_ok (opcode1, insn1, opcode2, insn2, exec_type))
8085f210c2aSfgsch 	{
8095f210c2aSfgsch 	  /* Parallel.  */
810fddef416Sniklas 	  if (opcode1->unit == IU)
811fddef416Sniklas 	    insn = FM00 | (insn2 << 15) | insn1;
812fddef416Sniklas 	  else if (opcode2->unit == MU)
813fddef416Sniklas 	    insn = FM00 | (insn2 << 15) | insn1;
814fddef416Sniklas 	  else
815fddef416Sniklas 	    insn = FM00 | (insn1 << 15) | insn2;
816fddef416Sniklas 	}
817fddef416Sniklas       else if (opcode1->unit == IU)
8185f210c2aSfgsch 	/* Reverse sequential with IU opcode1 on right and done first.  */
819fddef416Sniklas 	insn = FM10 | (insn2 << 15) | insn1;
820fddef416Sniklas       else
8215f210c2aSfgsch 	/* Sequential with non-IU opcode1 on left and done first.  */
822fddef416Sniklas 	insn = FM01 | (insn1 << 15) | insn2;
823fddef416Sniklas       break;
824fddef416Sniklas 
8255f210c2aSfgsch     case PACK_PARALLEL:
8265f210c2aSfgsch       if (opcode1->exec_type & SEQ || opcode2->exec_type & SEQ)
8275f210c2aSfgsch 	as_fatal
8285f210c2aSfgsch 	  (_("One of these instructions may not be executed in parallel."));
829fddef416Sniklas       if (opcode1->unit == IU)
830fddef416Sniklas 	{
831fddef416Sniklas 	  if (opcode2->unit == IU)
832f7cc78ecSespie 	    as_fatal (_("Two IU instructions may not be executed in parallel"));
833f7cc78ecSespie 	  if (!flag_warn_suppress_instructionswap)
834f7cc78ecSespie 	    as_warn (_("Swapping instruction order"));
835fddef416Sniklas 	  insn = FM00 | (insn2 << 15) | insn1;
836fddef416Sniklas 	}
837fddef416Sniklas       else if (opcode2->unit == MU)
838fddef416Sniklas 	{
839fddef416Sniklas 	  if (opcode1->unit == MU)
840f7cc78ecSespie 	    as_fatal (_("Two MU instructions may not be executed in parallel"));
841f7cc78ecSespie 	  if (!flag_warn_suppress_instructionswap)
842f7cc78ecSespie 	    as_warn (_("Swapping instruction order"));
843fddef416Sniklas 	  insn = FM00 | (insn2 << 15) | insn1;
844fddef416Sniklas 	}
845fddef416Sniklas       else
846fddef416Sniklas 	insn = FM00 | (insn1 << 15) | insn2;
847d2201f2fSdrahn       check_resource_conflict (opcode1, insn1, opcode2, insn2);
848fddef416Sniklas       break;
8495f210c2aSfgsch 
8505f210c2aSfgsch     case PACK_LEFT_RIGHT:
851f7cc78ecSespie       if (opcode1->unit != IU)
852fddef416Sniklas 	insn = FM01 | (insn1 << 15) | insn2;
853f7cc78ecSespie       else if (opcode2->unit == MU || opcode2->unit == EITHER)
854f7cc78ecSespie 	{
855f7cc78ecSespie 	  if (!flag_warn_suppress_instructionswap)
856f7cc78ecSespie 	    as_warn (_("Swapping instruction order"));
857f7cc78ecSespie 	  insn = FM10 | (insn2 << 15) | insn1;
858f7cc78ecSespie 	}
859f7cc78ecSespie       else
860f7cc78ecSespie 	as_fatal (_("IU instruction may not be in the left container"));
8615f210c2aSfgsch       if (opcode1->exec_type & ALONE)
8625f210c2aSfgsch 	as_warn (_("Instruction in R container is squashed by flow control instruction in L container."));
863fddef416Sniklas       break;
8645f210c2aSfgsch 
8655f210c2aSfgsch     case PACK_RIGHT_LEFT:
866f7cc78ecSespie       if (opcode2->unit != MU)
867fddef416Sniklas 	insn = FM10 | (insn1 << 15) | insn2;
868f7cc78ecSespie       else if (opcode1->unit == IU || opcode1->unit == EITHER)
869f7cc78ecSespie 	{
870f7cc78ecSespie 	  if (!flag_warn_suppress_instructionswap)
871f7cc78ecSespie 	    as_warn (_("Swapping instruction order"));
872f7cc78ecSespie 	  insn = FM01 | (insn2 << 15) | insn1;
873f7cc78ecSespie 	}
874f7cc78ecSespie       else
875f7cc78ecSespie 	as_fatal (_("MU instruction may not be in the right container"));
8765f210c2aSfgsch       if (opcode2->exec_type & ALONE)
8775f210c2aSfgsch 	as_warn (_("Instruction in R container is squashed by flow control instruction in L container."));
878fddef416Sniklas       break;
8795f210c2aSfgsch 
880fddef416Sniklas     default:
881f7cc78ecSespie       as_fatal (_("unknown execution type passed to write_2_short()"));
882fddef416Sniklas     }
883fddef416Sniklas 
884fddef416Sniklas   f = frag_more (4);
885fddef416Sniklas   number_to_chars_bigendian (f, insn, 4);
886fddef416Sniklas 
887d2201f2fSdrahn   /* Process fixup chains.  fx refers to insn2 when j == 0, and to
888d2201f2fSdrahn      insn1 when j == 1.  Yes, it's reversed.  */
8895f210c2aSfgsch 
890fddef416Sniklas   for (j = 0; j < 2; j++)
891fddef416Sniklas     {
892fddef416Sniklas       for (i = 0; i < fx->fc; i++)
893fddef416Sniklas 	{
894fddef416Sniklas 	  if (fx->fix[i].reloc)
895fddef416Sniklas 	    {
896fddef416Sniklas 	      where = f - frag_now->fr_literal;
897fddef416Sniklas 	      if (fx->fix[i].size == 2)
898fddef416Sniklas 		where += 2;
899fddef416Sniklas 
900d2201f2fSdrahn 	      if (fx->fix[i].reloc == BFD_RELOC_D10V_10_PCREL_R
901d2201f2fSdrahn 		  /* A BFD_RELOC_D10V_10_PCREL_R relocation applied to
902d2201f2fSdrahn 		     the instruction in the L container has to be
903d2201f2fSdrahn 		     adjusted to BDF_RELOC_D10V_10_PCREL_L.  When
904d2201f2fSdrahn 		     j==0, we're processing insn2's operands, so we
905d2201f2fSdrahn 		     want to mark the operand if insn2 is *not* in the
906d2201f2fSdrahn 		     R container.  When j==1, we're processing insn1's
907d2201f2fSdrahn 		     operands, so we want to mark the operand if insn2
908d2201f2fSdrahn 		     *is* in the R container.  Note that, if two
909d2201f2fSdrahn 		     instructions are identical, we're never going to
910d2201f2fSdrahn 		     swap them, so the test is safe.  */
911d2201f2fSdrahn 		  && j == ((insn & 0x7fff) == insn2))
912fddef416Sniklas 		fx->fix[i].operand |= 1024;
913fddef416Sniklas 
914fddef416Sniklas 	      if (fx->fix[i].reloc == BFD_RELOC_D10V_18)
915fddef416Sniklas 		fx->fix[i].operand |= 4096;
916fddef416Sniklas 
917fddef416Sniklas 	      fix_new_exp (frag_now,
918fddef416Sniklas 			   where,
919fddef416Sniklas 			   fx->fix[i].size,
920fddef416Sniklas 			   &(fx->fix[i].exp),
921fddef416Sniklas 			   fx->fix[i].pcrel,
922fddef416Sniklas 			   fx->fix[i].operand|2048);
923fddef416Sniklas 	    }
924fddef416Sniklas 	}
925fddef416Sniklas       fx->fc = 0;
926fddef416Sniklas       fx = fx->next;
927fddef416Sniklas     }
928fddef416Sniklas   return (0);
929fddef416Sniklas }
930fddef416Sniklas 
9315f210c2aSfgsch /* Check 2 instructions and determine if they can be safely
9325f210c2aSfgsch    executed in parallel.  Return 1 if they can be.  */
933fddef416Sniklas 
934fddef416Sniklas static int
parallel_ok(op1,insn1,op2,insn2,exec_type)935fddef416Sniklas parallel_ok (op1, insn1, op2, insn2, exec_type)
936fddef416Sniklas      struct d10v_opcode *op1, *op2;
937fddef416Sniklas      unsigned long insn1, insn2;
9385f210c2aSfgsch      packing_type exec_type;
939fddef416Sniklas {
940fddef416Sniklas   int i, j, flags, mask, shift, regno;
941fddef416Sniklas   unsigned long ins, mod[2], used[2];
942fddef416Sniklas   struct d10v_opcode *op;
943fddef416Sniklas 
944fddef416Sniklas   if ((op1->exec_type & SEQ) != 0 || (op2->exec_type & SEQ) != 0
945fddef416Sniklas       || (op1->exec_type & PAR) == 0 || (op2->exec_type & PAR) == 0
946fddef416Sniklas       || (op1->unit == BOTH) || (op2->unit == BOTH)
947fddef416Sniklas       || (op1->unit == IU && op2->unit == IU)
948fddef416Sniklas       || (op1->unit == MU && op2->unit == MU))
949fddef416Sniklas     return 0;
950fddef416Sniklas 
951d2201f2fSdrahn   /* If this is auto parallelization, and the first instruction is a
952d2201f2fSdrahn      branch or should not be packed, then don't parallelize.  */
9535f210c2aSfgsch   if (exec_type == PACK_UNSPEC
954d2201f2fSdrahn       && (op1->exec_type & (ALONE | BRANCH)))
955fddef416Sniklas     return 0;
956fddef416Sniklas 
957f7cc78ecSespie   /* The idea here is to create two sets of bitmasks (mod and used)
958f7cc78ecSespie      which indicate which registers are modified or used by each
959f7cc78ecSespie      instruction.  The operation can only be done in parallel if
960f7cc78ecSespie      instruction 1 and instruction 2 modify different registers, and
961f7cc78ecSespie      the first instruction does not modify registers that the second
962f7cc78ecSespie      is using (The second instruction can modify registers that the
963f7cc78ecSespie      first is using as they are only written back after the first
964f7cc78ecSespie      instruction has completed).  Accesses to control registers, PSW,
965f7cc78ecSespie      and memory are treated as accesses to a single register.  So if
966f7cc78ecSespie      both instructions write memory or if the first instruction writes
967f7cc78ecSespie      memory and the second reads, then they cannot be done in
968f7cc78ecSespie      parallel.  Likewise, if the first instruction mucks with the psw
969f7cc78ecSespie      and the second reads the PSW (which includes C, F0, and F1), then
970f7cc78ecSespie      they cannot operate safely in parallel.  */
971fddef416Sniklas 
972d2201f2fSdrahn   /* The bitmasks (mod and used) look like this (bit 31 = MSB).
973d2201f2fSdrahn      r0-r15	  0-15
974d2201f2fSdrahn      a0-a1	  16-17
975d2201f2fSdrahn      cr (not psw) 18
976d2201f2fSdrahn      psw	  19
977d2201f2fSdrahn      mem	  20  */
978fddef416Sniklas 
979fddef416Sniklas   for (j = 0; j < 2; j++)
980fddef416Sniklas     {
981fddef416Sniklas       if (j == 0)
982fddef416Sniklas 	{
983fddef416Sniklas 	  op = op1;
984fddef416Sniklas 	  ins = insn1;
985fddef416Sniklas 	}
986fddef416Sniklas       else
987fddef416Sniklas 	{
988fddef416Sniklas 	  op = op2;
989fddef416Sniklas 	  ins = insn2;
990fddef416Sniklas 	}
991fddef416Sniklas       mod[j] = used[j] = 0;
992fddef416Sniklas       if (op->exec_type & BRANCH_LINK)
993fddef416Sniklas 	mod[j] |= 1 << 13;
994fddef416Sniklas 
995fddef416Sniklas       for (i = 0; op->operands[i]; i++)
996fddef416Sniklas 	{
997fddef416Sniklas 	  flags = d10v_operands[op->operands[i]].flags;
998fddef416Sniklas 	  shift = d10v_operands[op->operands[i]].shift;
999fddef416Sniklas 	  mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits);
1000fddef416Sniklas 	  if (flags & OPERAND_REG)
1001fddef416Sniklas 	    {
1002fddef416Sniklas 	      regno = (ins >> shift) & mask;
1003f7cc78ecSespie 	      if (flags & (OPERAND_ACC0 | OPERAND_ACC1))
1004fddef416Sniklas 		regno += 16;
10055f210c2aSfgsch 	      else if (flags & OPERAND_CONTROL)	/* mvtc or mvfc.  */
1006fddef416Sniklas 		{
1007fddef416Sniklas 		  if (regno == 0)
1008fddef416Sniklas 		    regno = 19;
1009fddef416Sniklas 		  else
1010fddef416Sniklas 		    regno = 18;
1011fddef416Sniklas 		}
1012f7cc78ecSespie 	      else if (flags & (OPERAND_FFLAG | OPERAND_CFLAG))
1013fddef416Sniklas 		regno = 19;
1014fddef416Sniklas 
1015fddef416Sniklas 	      if (flags & OPERAND_DEST)
1016fddef416Sniklas 		{
1017fddef416Sniklas 		  mod[j] |= 1 << regno;
1018fddef416Sniklas 		  if (flags & OPERAND_EVEN)
1019fddef416Sniklas 		    mod[j] |= 1 << (regno + 1);
1020fddef416Sniklas 		}
1021fddef416Sniklas 	      else
1022fddef416Sniklas 		{
1023fddef416Sniklas 		  used[j] |= 1 << regno;
1024fddef416Sniklas 		  if (flags & OPERAND_EVEN)
1025fddef416Sniklas 		    used[j] |= 1 << (regno + 1);
1026f7cc78ecSespie 
1027f7cc78ecSespie 		  /* Auto inc/dec also modifies the register.  */
1028f7cc78ecSespie 		  if (op->operands[i + 1] != 0
1029f7cc78ecSespie 		      && (d10v_operands[op->operands[i + 1]].flags
1030f7cc78ecSespie 			  & (OPERAND_PLUS | OPERAND_MINUS)) != 0)
1031f7cc78ecSespie 		    mod[j] |= 1 << regno;
1032fddef416Sniklas 		}
1033fddef416Sniklas 	    }
1034f7cc78ecSespie 	  else if (flags & OPERAND_ATMINUS)
1035f7cc78ecSespie 	    {
10365f210c2aSfgsch 	      /* SP implicitly used/modified.  */
1037f7cc78ecSespie 	      mod[j] |= 1 << 15;
1038f7cc78ecSespie 	      used[j] |= 1 << 15;
1039f7cc78ecSespie 	    }
1040fddef416Sniklas 	}
1041fddef416Sniklas       if (op->exec_type & RMEM)
1042fddef416Sniklas 	used[j] |= 1 << 20;
1043fddef416Sniklas       else if (op->exec_type & WMEM)
1044fddef416Sniklas 	mod[j] |= 1 << 20;
1045fddef416Sniklas       else if (op->exec_type & RF0)
1046fddef416Sniklas 	used[j] |= 1 << 19;
1047fddef416Sniklas       else if (op->exec_type & WF0)
1048fddef416Sniklas 	mod[j] |= 1 << 19;
1049fddef416Sniklas       else if (op->exec_type & WCAR)
1050fddef416Sniklas 	mod[j] |= 1 << 19;
1051fddef416Sniklas     }
1052f7cc78ecSespie   if ((mod[0] & mod[1]) == 0 && (mod[0] & used[1]) == 0)
1053fddef416Sniklas     return 1;
1054fddef416Sniklas   return 0;
1055fddef416Sniklas }
1056fddef416Sniklas 
1057d2201f2fSdrahn /* Determine if there are any resource conflicts among two manually
1058d2201f2fSdrahn    parallelized instructions.  Some of this was lifted from parallel_ok.  */
1059d2201f2fSdrahn 
1060d2201f2fSdrahn static void
check_resource_conflict(op1,insn1,op2,insn2)1061d2201f2fSdrahn check_resource_conflict (op1, insn1, op2, insn2)
1062d2201f2fSdrahn      struct d10v_opcode *op1, *op2;
1063d2201f2fSdrahn      unsigned long insn1, insn2;
1064d2201f2fSdrahn {
1065d2201f2fSdrahn   int i, j, flags, mask, shift, regno;
1066d2201f2fSdrahn   unsigned long ins, mod[2];
1067d2201f2fSdrahn   struct d10v_opcode *op;
1068d2201f2fSdrahn 
1069d2201f2fSdrahn   if ((op1->exec_type & SEQ)
1070d2201f2fSdrahn       || ! ((op1->exec_type & PAR) || (op1->exec_type & PARONLY)))
1071d2201f2fSdrahn     {
1072d2201f2fSdrahn       as_warn (_("packing conflict: %s must dispatch sequentially"),
1073d2201f2fSdrahn 	      op1->name);
1074d2201f2fSdrahn       return;
1075d2201f2fSdrahn     }
1076d2201f2fSdrahn 
1077d2201f2fSdrahn   if ((op2->exec_type & SEQ)
1078d2201f2fSdrahn       || ! ((op2->exec_type & PAR) || (op2->exec_type & PARONLY)))
1079d2201f2fSdrahn     {
1080d2201f2fSdrahn       as_warn (_("packing conflict: %s must dispatch sequentially"),
1081d2201f2fSdrahn 	      op2->name);
1082d2201f2fSdrahn       return;
1083d2201f2fSdrahn     }
1084d2201f2fSdrahn 
1085d2201f2fSdrahn    /* See if both instructions write to the same resource.
1086d2201f2fSdrahn 
1087d2201f2fSdrahn       The idea here is to create two sets of bitmasks (mod and used) which
1088d2201f2fSdrahn       indicate which registers are modified or used by each instruction.
1089d2201f2fSdrahn       The operation can only be done in parallel if neither instruction
1090d2201f2fSdrahn       modifies the same register. Accesses to control registers and memory
1091d2201f2fSdrahn       are treated as accesses to a single register. So if both instructions
1092d2201f2fSdrahn       write memory or if the first instruction writes memory and the second
1093d2201f2fSdrahn       reads, then they cannot be done in parallel. We treat reads to the PSW
1094d2201f2fSdrahn       (which includes C, F0, and F1) in isolation. So simultaneously writing
1095d2201f2fSdrahn       C and F0 in two different sub-instructions is permitted.  */
1096d2201f2fSdrahn 
1097d2201f2fSdrahn   /* The bitmasks (mod and used) look like this (bit 31 = MSB).
1098d2201f2fSdrahn      r0-r15	  0-15
1099d2201f2fSdrahn      a0-a1	  16-17
1100d2201f2fSdrahn      cr (not psw) 18
1101d2201f2fSdrahn      psw(other)   19
1102d2201f2fSdrahn      mem	  20
1103d2201f2fSdrahn      psw(C flag)  21
1104d2201f2fSdrahn      psw(F0 flag) 22  */
1105d2201f2fSdrahn 
1106d2201f2fSdrahn   for (j = 0; j < 2; j++)
1107d2201f2fSdrahn     {
1108d2201f2fSdrahn       if (j == 0)
1109d2201f2fSdrahn 	{
1110d2201f2fSdrahn 	  op = op1;
1111d2201f2fSdrahn 	  ins = insn1;
1112d2201f2fSdrahn 	}
1113d2201f2fSdrahn       else
1114d2201f2fSdrahn 	{
1115d2201f2fSdrahn 	  op = op2;
1116d2201f2fSdrahn 	  ins = insn2;
1117d2201f2fSdrahn 	}
1118d2201f2fSdrahn       mod[j] = 0;
1119d2201f2fSdrahn       if (op->exec_type & BRANCH_LINK)
1120d2201f2fSdrahn 	mod[j] |= 1 << 13;
1121d2201f2fSdrahn 
1122d2201f2fSdrahn       for (i = 0; op->operands[i]; i++)
1123d2201f2fSdrahn 	{
1124d2201f2fSdrahn 	  flags = d10v_operands[op->operands[i]].flags;
1125d2201f2fSdrahn 	  shift = d10v_operands[op->operands[i]].shift;
1126d2201f2fSdrahn 	  mask = 0x7FFFFFFF >> (31 - d10v_operands[op->operands[i]].bits);
1127d2201f2fSdrahn 	  if (flags & OPERAND_REG)
1128d2201f2fSdrahn 	    {
1129d2201f2fSdrahn 	      regno = (ins >> shift) & mask;
1130d2201f2fSdrahn 	      if (flags & (OPERAND_ACC0 | OPERAND_ACC1))
1131d2201f2fSdrahn 		regno += 16;
1132d2201f2fSdrahn 	      else if (flags & OPERAND_CONTROL)	/* mvtc or mvfc */
1133d2201f2fSdrahn 		{
1134d2201f2fSdrahn 		  if (regno == 0)
1135d2201f2fSdrahn 		    regno = 19;
1136d2201f2fSdrahn 		  else
1137d2201f2fSdrahn 		    regno = 18;
1138d2201f2fSdrahn 		}
1139d2201f2fSdrahn 	      else if (flags & OPERAND_FFLAG)
1140d2201f2fSdrahn 		regno = 22;
1141d2201f2fSdrahn 	      else if (flags & OPERAND_CFLAG)
1142d2201f2fSdrahn 		regno = 21;
1143d2201f2fSdrahn 
1144d2201f2fSdrahn 	      if (flags & OPERAND_DEST
1145d2201f2fSdrahn 		  /* Auto inc/dec also modifies the register.  */
1146d2201f2fSdrahn 		  || (op->operands[i + 1] != 0
1147d2201f2fSdrahn 		      && (d10v_operands[op->operands[i + 1]].flags
1148d2201f2fSdrahn 			  & (OPERAND_PLUS | OPERAND_MINUS)) != 0))
1149d2201f2fSdrahn 		{
1150d2201f2fSdrahn 		  mod[j] |= 1 << regno;
1151d2201f2fSdrahn 		  if (flags & OPERAND_EVEN)
1152d2201f2fSdrahn 		    mod[j] |= 1 << (regno + 1);
1153d2201f2fSdrahn 		}
1154d2201f2fSdrahn 	    }
1155d2201f2fSdrahn 	  else if (flags & OPERAND_ATMINUS)
1156d2201f2fSdrahn 	    {
1157d2201f2fSdrahn 	      /* SP implicitly used/modified.  */
1158d2201f2fSdrahn 	      mod[j] |= 1 << 15;
1159d2201f2fSdrahn 	    }
1160d2201f2fSdrahn 	}
1161d2201f2fSdrahn 
1162d2201f2fSdrahn       if (op->exec_type & WMEM)
1163d2201f2fSdrahn 	mod[j] |= 1 << 20;
1164d2201f2fSdrahn       else if (op->exec_type & WF0)
1165d2201f2fSdrahn 	mod[j] |= 1 << 22;
1166d2201f2fSdrahn       else if (op->exec_type & WCAR)
1167d2201f2fSdrahn 	mod[j] |= 1 << 21;
1168d2201f2fSdrahn     }
1169d2201f2fSdrahn 
1170d2201f2fSdrahn   if ((mod[0] & mod[1]) == 0)
1171d2201f2fSdrahn     return;
1172d2201f2fSdrahn   else
1173d2201f2fSdrahn     {
1174d2201f2fSdrahn       unsigned long x;
1175d2201f2fSdrahn       x = mod[0] & mod[1];
1176d2201f2fSdrahn 
1177d2201f2fSdrahn       for (j = 0; j <= 15; j++)
1178d2201f2fSdrahn 	if (x & (1 << j))
1179d2201f2fSdrahn 	  as_warn (_("resource conflict (R%d)"), j);
1180d2201f2fSdrahn       for (j = 16; j <= 17; j++)
1181d2201f2fSdrahn 	if (x & (1 << j))
1182d2201f2fSdrahn 	  as_warn (_("resource conflict (A%d)"), j - 16);
1183d2201f2fSdrahn       if (x & (1 << 19))
1184d2201f2fSdrahn 	as_warn (_("resource conflict (PSW)"));
1185d2201f2fSdrahn       if (x & (1 << 21))
1186d2201f2fSdrahn 	as_warn (_("resource conflict (C flag)"));
1187d2201f2fSdrahn       if (x & (1 << 22))
1188d2201f2fSdrahn 	as_warn (_("resource conflict (F flag)"));
1189d2201f2fSdrahn     }
1190d2201f2fSdrahn }
1191d2201f2fSdrahn 
11925f210c2aSfgsch /* This is the main entry point for the machine-dependent assembler.
1193d2201f2fSdrahn    str points to a machine-dependent instruction.  This function is
11945f210c2aSfgsch    supposed to emit the frags/bytes it assembles to.  For the D10V, it
11955f210c2aSfgsch    mostly handles the special VLIW parsing and packing and leaves the
11965f210c2aSfgsch    difficult stuff to do_assemble().  */
1197fddef416Sniklas 
1198fddef416Sniklas static unsigned long prev_insn;
1199fddef416Sniklas static struct d10v_opcode *prev_opcode = 0;
1200fddef416Sniklas static subsegT prev_subseg;
1201fddef416Sniklas static segT prev_seg = 0;;
1202fddef416Sniklas 
1203fddef416Sniklas void
md_assemble(str)1204fddef416Sniklas md_assemble (str)
1205fddef416Sniklas      char *str;
1206fddef416Sniklas {
12075f210c2aSfgsch   /* etype is saved extype.  For multi-line instructions.  */
12085f210c2aSfgsch 
12095f210c2aSfgsch   packing_type extype = PACK_UNSPEC;		/* Parallel, etc.  */
12105f210c2aSfgsch 
1211fddef416Sniklas   struct d10v_opcode *opcode;
1212fddef416Sniklas   unsigned long insn;
1213fddef416Sniklas   char *str2;
1214fddef416Sniklas 
12155f210c2aSfgsch   if (etype == PACK_UNSPEC)
1216fddef416Sniklas     {
12175f210c2aSfgsch       /* Look for the special multiple instruction separators.  */
1218fddef416Sniklas       str2 = strstr (str, "||");
1219fddef416Sniklas       if (str2)
12205f210c2aSfgsch 	extype = PACK_PARALLEL;
1221fddef416Sniklas       else
1222fddef416Sniklas 	{
1223fddef416Sniklas 	  str2 = strstr (str, "->");
1224fddef416Sniklas 	  if (str2)
12255f210c2aSfgsch 	    extype = PACK_LEFT_RIGHT;
1226fddef416Sniklas 	  else
1227fddef416Sniklas 	    {
1228fddef416Sniklas 	      str2 = strstr (str, "<-");
1229fddef416Sniklas 	      if (str2)
12305f210c2aSfgsch 		extype = PACK_RIGHT_LEFT;
1231fddef416Sniklas 	    }
1232fddef416Sniklas 	}
1233d2201f2fSdrahn 
1234d2201f2fSdrahn       /* str2 points to the separator, if there is one.  */
1235fddef416Sniklas       if (str2)
1236fddef416Sniklas 	{
1237fddef416Sniklas 	  *str2 = 0;
1238fddef416Sniklas 
12395f210c2aSfgsch 	  /* If two instructions are present and we already have one saved,
12405f210c2aSfgsch 	     then first write out the saved one.  */
1241fddef416Sniklas 	  d10v_cleanup ();
1242fddef416Sniklas 
12435f210c2aSfgsch 	  /* Assemble first instruction and save it.  */
1244fddef416Sniklas 	  prev_insn = do_assemble (str, &prev_opcode);
12455f210c2aSfgsch 	  prev_seg = now_seg;
12465f210c2aSfgsch 	  prev_subseg = now_subseg;
12475f210c2aSfgsch 	  if (prev_insn == (unsigned long) -1)
1248f7cc78ecSespie 	    as_fatal (_("can't find opcode "));
1249fddef416Sniklas 	  fixups = fixups->next;
1250fddef416Sniklas 	  str = str2 + 2;
1251fddef416Sniklas 	}
1252fddef416Sniklas     }
1253fddef416Sniklas 
1254fddef416Sniklas   insn = do_assemble (str, &opcode);
12555f210c2aSfgsch   if (insn == (unsigned long) -1)
1256fddef416Sniklas     {
12575f210c2aSfgsch       if (extype != PACK_UNSPEC)
1258fddef416Sniklas 	{
1259fddef416Sniklas 	  etype = extype;
1260fddef416Sniklas 	  return;
1261fddef416Sniklas 	}
1262f7cc78ecSespie       as_fatal (_("can't find opcode "));
1263fddef416Sniklas     }
1264fddef416Sniklas 
12655f210c2aSfgsch   if (etype != PACK_UNSPEC)
1266fddef416Sniklas     {
1267fddef416Sniklas       extype = etype;
12685f210c2aSfgsch       etype = PACK_UNSPEC;
1269fddef416Sniklas     }
1270fddef416Sniklas 
12715f210c2aSfgsch   /* If this is a long instruction, write it and any previous short
12725f210c2aSfgsch      instruction.  */
1273fddef416Sniklas   if (opcode->format & LONG_OPCODE)
1274fddef416Sniklas     {
12755f210c2aSfgsch       if (extype != PACK_UNSPEC)
1276f7cc78ecSespie 	as_fatal (_("Unable to mix instructions as specified"));
1277fddef416Sniklas       d10v_cleanup ();
12785f210c2aSfgsch       write_long (insn, fixups);
1279fddef416Sniklas       prev_opcode = NULL;
1280fddef416Sniklas       return;
1281fddef416Sniklas     }
1282fddef416Sniklas 
12835f210c2aSfgsch   if (prev_opcode
12845f210c2aSfgsch       && prev_seg
12855f210c2aSfgsch       && ((prev_seg != now_seg) || (prev_subseg != now_subseg)))
1286fddef416Sniklas     d10v_cleanup ();
1287fddef416Sniklas 
12885f210c2aSfgsch   if (prev_opcode
1289d2201f2fSdrahn       && (0 == write_2_short (prev_opcode, prev_insn, opcode, insn, extype,
1290d2201f2fSdrahn 			      fixups)))
1291fddef416Sniklas     {
12925f210c2aSfgsch       /* No instructions saved.  */
1293fddef416Sniklas       prev_opcode = NULL;
1294fddef416Sniklas     }
1295fddef416Sniklas   else
1296fddef416Sniklas     {
12975f210c2aSfgsch       if (extype != PACK_UNSPEC)
1298f7cc78ecSespie 	as_fatal (_("Unable to mix instructions as specified"));
12995f210c2aSfgsch       /* Save last instruction so it may be packed on next pass.  */
1300fddef416Sniklas       prev_opcode = opcode;
1301fddef416Sniklas       prev_insn = insn;
1302fddef416Sniklas       prev_seg = now_seg;
1303fddef416Sniklas       prev_subseg = now_subseg;
1304fddef416Sniklas       fixups = fixups->next;
1305fddef416Sniklas     }
1306fddef416Sniklas }
1307fddef416Sniklas 
13085f210c2aSfgsch /* Assemble a single instruction.
13095f210c2aSfgsch    Return an opcode, or -1 (an invalid opcode) on error.  */
1310fddef416Sniklas 
1311fddef416Sniklas static unsigned long
do_assemble(str,opcode)1312fddef416Sniklas do_assemble (str, opcode)
1313fddef416Sniklas      char *str;
1314fddef416Sniklas      struct d10v_opcode **opcode;
1315fddef416Sniklas {
1316fddef416Sniklas   unsigned char *op_start, *save;
1317fddef416Sniklas   unsigned char *op_end;
1318fddef416Sniklas   char name[20];
1319fddef416Sniklas   int nlen = 0;
1320fddef416Sniklas   expressionS myops[6];
1321fddef416Sniklas   unsigned long insn;
1322fddef416Sniklas 
1323f7cc78ecSespie   /* Drop leading whitespace.  */
1324fddef416Sniklas   while (*str == ' ')
1325fddef416Sniklas     str++;
1326fddef416Sniklas 
1327f7cc78ecSespie   /* Find the opcode end.  */
1328fddef416Sniklas   for (op_start = op_end = (unsigned char *) (str);
1329fddef416Sniklas        *op_end
1330fddef416Sniklas        && nlen < 20
1331fddef416Sniklas        && !is_end_of_line[*op_end] && *op_end != ' ';
1332fddef416Sniklas        op_end++)
1333fddef416Sniklas     {
1334d2201f2fSdrahn       name[nlen] = TOLOWER (op_start[nlen]);
1335fddef416Sniklas       nlen++;
1336fddef416Sniklas     }
1337fddef416Sniklas   name[nlen] = 0;
1338fddef416Sniklas 
1339fddef416Sniklas   if (nlen == 0)
1340f7cc78ecSespie     return -1;
1341fddef416Sniklas 
1342f7cc78ecSespie   /* Find the first opcode with the proper name.  */
1343fddef416Sniklas   *opcode = (struct d10v_opcode *) hash_find (d10v_hash, name);
1344fddef416Sniklas   if (*opcode == NULL)
1345f7cc78ecSespie     as_fatal (_("unknown opcode: %s"), name);
1346fddef416Sniklas 
1347fddef416Sniklas   save = input_line_pointer;
1348fddef416Sniklas   input_line_pointer = op_end;
1349fddef416Sniklas   *opcode = find_opcode (*opcode, myops);
1350fddef416Sniklas   if (*opcode == 0)
1351fddef416Sniklas     return -1;
1352fddef416Sniklas   input_line_pointer = save;
1353fddef416Sniklas 
1354fddef416Sniklas   insn = build_insn ((*opcode), myops, 0);
1355fddef416Sniklas   return (insn);
1356fddef416Sniklas }
1357fddef416Sniklas 
1358d2201f2fSdrahn /* Find the symbol which has the same name as the register in exp.  */
13595f210c2aSfgsch 
1360f7cc78ecSespie static symbolS *
find_symbol_matching_register(exp)1361f7cc78ecSespie find_symbol_matching_register (exp)
1362f7cc78ecSespie      expressionS *exp;
1363f7cc78ecSespie {
1364f7cc78ecSespie   int i;
1365f7cc78ecSespie 
1366f7cc78ecSespie   if (exp->X_op != O_register)
1367f7cc78ecSespie     return NULL;
1368f7cc78ecSespie 
1369f7cc78ecSespie   /* Find the name of the register.  */
1370f7cc78ecSespie   for (i = d10v_reg_name_cnt (); i--;)
1371f7cc78ecSespie     if (d10v_predefined_registers[i].value == exp->X_add_number)
1372f7cc78ecSespie       break;
1373f7cc78ecSespie 
1374f7cc78ecSespie   if (i < 0)
1375f7cc78ecSespie     abort ();
1376f7cc78ecSespie 
1377f7cc78ecSespie   /* Now see if a symbol has been defined with the same name.  */
1378f7cc78ecSespie   return symbol_find (d10v_predefined_registers[i].name);
1379f7cc78ecSespie }
1380f7cc78ecSespie 
13815f210c2aSfgsch /* Get a pointer to an entry in the opcode table.
13825f210c2aSfgsch    The function must look at all opcodes with the same name and use
13835f210c2aSfgsch    the operands to choose the correct opcode.  */
1384fddef416Sniklas 
1385fddef416Sniklas static struct d10v_opcode *
find_opcode(opcode,myops)1386fddef416Sniklas find_opcode (opcode, myops)
1387fddef416Sniklas      struct d10v_opcode *opcode;
1388fddef416Sniklas      expressionS myops[];
1389fddef416Sniklas {
13905f210c2aSfgsch   int i, match;
1391fddef416Sniklas   struct d10v_opcode *next_opcode;
1392fddef416Sniklas 
13935f210c2aSfgsch   /* Get all the operands and save them as expressions.  */
1394fddef416Sniklas   get_operands (myops);
1395fddef416Sniklas 
13965f210c2aSfgsch   /* Now see if the operand is a fake.  If so, find the correct size
13975f210c2aSfgsch      instruction, if possible.  */
1398fddef416Sniklas   if (opcode->format == OPCODE_FAKE)
1399fddef416Sniklas     {
1400fddef416Sniklas       int opnum = opcode->operands[0];
1401f7cc78ecSespie       int flags;
1402fddef416Sniklas 
1403fddef416Sniklas       if (myops[opnum].X_op == O_register)
1404fddef416Sniklas 	{
1405fddef416Sniklas 	  myops[opnum].X_op = O_symbol;
14065f210c2aSfgsch 	  myops[opnum].X_add_symbol =
14075f210c2aSfgsch 	    symbol_find_or_make ((char *) myops[opnum].X_op_symbol);
1408fddef416Sniklas 	  myops[opnum].X_add_number = 0;
1409fddef416Sniklas 	  myops[opnum].X_op_symbol = NULL;
1410fddef416Sniklas 	}
1411fddef416Sniklas 
1412f7cc78ecSespie       next_opcode = opcode + 1;
1413f7cc78ecSespie 
1414f7cc78ecSespie       /* If the first operand is supposed to be a register, make sure
1415f7cc78ecSespie 	 we got a valid one.  */
1416f7cc78ecSespie       flags = d10v_operands[next_opcode->operands[0]].flags;
1417f7cc78ecSespie       if (flags & OPERAND_REG)
1418f7cc78ecSespie 	{
1419f7cc78ecSespie 	  int X_op = myops[0].X_op;
1420f7cc78ecSespie 	  int num = myops[0].X_add_number;
1421f7cc78ecSespie 
1422f7cc78ecSespie 	  if (X_op != O_register
1423f7cc78ecSespie 	      || (num & ~flags
1424f7cc78ecSespie 		  & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1
1425d2201f2fSdrahn 		     | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL))
1426d2201f2fSdrahn 	      || ((flags & OPERAND_SP) && ! (num & OPERAND_SP)))
1427f7cc78ecSespie 	    {
1428f7cc78ecSespie 	      as_bad (_("bad opcode or operands"));
1429f7cc78ecSespie 	      return 0;
1430f7cc78ecSespie 	    }
1431f7cc78ecSespie 	}
1432f7cc78ecSespie 
14335f210c2aSfgsch       if (myops[opnum].X_op == O_constant
14345f210c2aSfgsch 	  || (myops[opnum].X_op == O_symbol
14355f210c2aSfgsch 	      && S_IS_DEFINED (myops[opnum].X_add_symbol)
14365f210c2aSfgsch 	      && (S_GET_SEGMENT (myops[opnum].X_add_symbol) == now_seg)))
1437fddef416Sniklas 	{
1438fddef416Sniklas 	  for (i = 0; opcode->operands[i + 1]; i++)
1439fddef416Sniklas 	    {
1440fddef416Sniklas 	      int bits = d10v_operands[next_opcode->operands[opnum]].bits;
1441fddef416Sniklas 	      int flags = d10v_operands[next_opcode->operands[opnum]].flags;
1442fddef416Sniklas 	      if (flags & OPERAND_ADDR)
1443fddef416Sniklas 		bits += 2;
14445f210c2aSfgsch 
1445fddef416Sniklas 	      if (myops[opnum].X_op == O_constant)
1446fddef416Sniklas 		{
1447fddef416Sniklas 		  if (!check_range (myops[opnum].X_add_number, bits, flags))
1448d2201f2fSdrahn 		    break;
1449fddef416Sniklas 		}
1450fddef416Sniklas 	      else
1451fddef416Sniklas 		{
14525f210c2aSfgsch 		  fragS *sym_frag;
1453fddef416Sniklas 		  fragS *f;
14545f210c2aSfgsch 		  unsigned long current_position;
14555f210c2aSfgsch 		  unsigned long symbol_position;
14565f210c2aSfgsch 		  unsigned long value;
1457d2201f2fSdrahn 		  bfd_boolean found_symbol;
14585f210c2aSfgsch 
14595f210c2aSfgsch 		  /* Calculate the address of the current instruction
14605f210c2aSfgsch 		     and the address of the symbol.  Do this by summing
14615f210c2aSfgsch 		     the offsets of previous frags until we reach the
14625f210c2aSfgsch 		     frag containing the symbol, and the current frag.  */
14635f210c2aSfgsch 		  sym_frag = symbol_get_frag (myops[opnum].X_add_symbol);
1464d2201f2fSdrahn 		  found_symbol = FALSE;
14655f210c2aSfgsch 
14665f210c2aSfgsch 		  current_position =
14675f210c2aSfgsch 		    obstack_next_free (&frchain_now->frch_obstack)
14685f210c2aSfgsch 		    - frag_now->fr_literal;
14695f210c2aSfgsch 		  symbol_position = S_GET_VALUE (myops[opnum].X_add_symbol);
14705f210c2aSfgsch 
14715f210c2aSfgsch 		  for (f = frchain_now->frch_root; f; f = f->fr_next)
14725f210c2aSfgsch 		    {
14735f210c2aSfgsch 		      current_position += f->fr_fix + f->fr_offset;
14745f210c2aSfgsch 
14755f210c2aSfgsch 		      if (f == sym_frag)
1476d2201f2fSdrahn 			found_symbol = TRUE;
14775f210c2aSfgsch 
14785f210c2aSfgsch 		      if (! found_symbol)
14795f210c2aSfgsch 			symbol_position += f->fr_fix + f->fr_offset;
14805f210c2aSfgsch 		    }
14815f210c2aSfgsch 
14825f210c2aSfgsch 		  value = symbol_position;
1483fddef416Sniklas 
1484fddef416Sniklas 		  if (flags & OPERAND_ADDR)
14855f210c2aSfgsch 		    value -= current_position;
1486fddef416Sniklas 
1487f7cc78ecSespie 		  if (AT_WORD_P (&myops[opnum]))
1488fddef416Sniklas 		    {
1489fddef416Sniklas 		      if (bits > 4)
1490fddef416Sniklas 			{
1491fddef416Sniklas 			  bits += 2;
1492fddef416Sniklas 			  if (!check_range (value, bits, flags))
1493d2201f2fSdrahn 			    break;
1494fddef416Sniklas 			}
1495fddef416Sniklas 		    }
1496fddef416Sniklas 		  else if (!check_range (value, bits, flags))
1497d2201f2fSdrahn 		    break;
1498fddef416Sniklas 		}
1499fddef416Sniklas 	      next_opcode++;
1500fddef416Sniklas 	    }
1501d2201f2fSdrahn 
1502d2201f2fSdrahn 	  if (opcode->operands [i + 1] == 0)
1503f7cc78ecSespie 	    as_fatal (_("value out of range"));
1504d2201f2fSdrahn 	  else
1505d2201f2fSdrahn 	    opcode = next_opcode;
1506fddef416Sniklas 	}
1507fddef416Sniklas       else
1508fddef416Sniklas 	{
15095f210c2aSfgsch 	  /* Not a constant, so use a long instruction.  */
1510d2201f2fSdrahn 	  opcode += 2;
1511fddef416Sniklas 	}
1512fddef416Sniklas     }
1513d2201f2fSdrahn 
1514fddef416Sniklas   match = 0;
1515d2201f2fSdrahn 
15165f210c2aSfgsch   /* Now search the opcode table table for one with operands
15175f210c2aSfgsch      that matches what we've got.  */
1518fddef416Sniklas   while (!match)
1519fddef416Sniklas     {
1520fddef416Sniklas       match = 1;
1521fddef416Sniklas       for (i = 0; opcode->operands[i]; i++)
1522fddef416Sniklas 	{
1523fddef416Sniklas 	  int flags = d10v_operands[opcode->operands[i]].flags;
1524fddef416Sniklas 	  int X_op = myops[i].X_op;
1525fddef416Sniklas 	  int num = myops[i].X_add_number;
1526fddef416Sniklas 
1527fddef416Sniklas 	  if (X_op == 0)
1528fddef416Sniklas 	    {
1529fddef416Sniklas 	      match = 0;
1530fddef416Sniklas 	      break;
1531fddef416Sniklas 	    }
1532fddef416Sniklas 
1533fddef416Sniklas 	  if (flags & OPERAND_REG)
1534fddef416Sniklas 	    {
1535f7cc78ecSespie 	      if ((X_op != O_register)
1536f7cc78ecSespie 		  || (num & ~flags
1537f7cc78ecSespie 		      & (OPERAND_GPR | OPERAND_ACC0 | OPERAND_ACC1
1538f7cc78ecSespie 			 | OPERAND_FFLAG | OPERAND_CFLAG
1539d2201f2fSdrahn 			 | OPERAND_CONTROL))
1540d2201f2fSdrahn 		  || ((flags & OPERAND_SP) && ! (num & OPERAND_SP)))
1541fddef416Sniklas 		{
1542fddef416Sniklas 		  match = 0;
1543fddef416Sniklas 		  break;
1544fddef416Sniklas 		}
1545fddef416Sniklas 	    }
1546fddef416Sniklas 
1547fddef416Sniklas 	  if (((flags & OPERAND_MINUS)   && ((X_op != O_absent) || (num != OPERAND_MINUS))) ||
1548fddef416Sniklas 	      ((flags & OPERAND_PLUS)    && ((X_op != O_absent) || (num != OPERAND_PLUS))) ||
1549fddef416Sniklas 	      ((flags & OPERAND_ATMINUS) && ((X_op != O_absent) || (num != OPERAND_ATMINUS))) ||
1550fddef416Sniklas 	      ((flags & OPERAND_ATPAR)   && ((X_op != O_absent) || (num != OPERAND_ATPAR))) ||
1551f7cc78ecSespie 	      ((flags & OPERAND_ATSIGN)  && ((X_op != O_absent) || ((num != OPERAND_ATSIGN) && (num != OPERAND_ATPAR)))))
1552fddef416Sniklas 	    {
1553fddef416Sniklas 	      match = 0;
1554fddef416Sniklas 	      break;
1555fddef416Sniklas 	    }
1556f7cc78ecSespie 
1557*cf2f2c56Smiod 	  /* Unfortunately, for the indirect operand in instructions such
1558d2201f2fSdrahn 	     as ``ldb r1, @(c,r14)'' this function can be passed
1559d2201f2fSdrahn 	     X_op == O_register (because 'c' is a valid register name).
1560d2201f2fSdrahn 	     However we cannot just ignore the case when X_op == O_register
1561d2201f2fSdrahn 	     but flags & OPERAND_REG is null, so we check to see if a symbol
1562d2201f2fSdrahn 	     of the same name as the register exists.  If the symbol does
1563d2201f2fSdrahn 	     exist, then the parser was unable to distinguish the two cases
1564d2201f2fSdrahn 	     and we fix things here. (Ref: PR14826)  */
1565f7cc78ecSespie 
1566f7cc78ecSespie 	  if (!(flags & OPERAND_REG) && (X_op == O_register))
1567f7cc78ecSespie 	    {
1568d2201f2fSdrahn 	      symbolS * sym;
1569d2201f2fSdrahn 
1570d2201f2fSdrahn 	      sym = find_symbol_matching_register (& myops[i]);
1571f7cc78ecSespie 
1572f7cc78ecSespie 	      if (sym != NULL)
1573f7cc78ecSespie 		{
15745f210c2aSfgsch 		  myops[i].X_op = X_op = O_symbol;
1575f7cc78ecSespie 		  myops[i].X_add_symbol = sym;
1576fddef416Sniklas 		}
1577f7cc78ecSespie 	      else
1578f7cc78ecSespie 		as_bad
1579f7cc78ecSespie 		  (_("illegal operand - register name found where none expected"));
1580f7cc78ecSespie 	    }
1581f7cc78ecSespie 	}
1582f7cc78ecSespie 
1583f7cc78ecSespie       /* We're only done if the operands matched so far AND there
1584f7cc78ecSespie 	     are no more to check.  */
1585fddef416Sniklas       if (match && myops[i].X_op == 0)
1586fddef416Sniklas 	break;
1587fddef416Sniklas       else
1588fddef416Sniklas 	match = 0;
1589fddef416Sniklas 
1590fddef416Sniklas       next_opcode = opcode + 1;
1591f7cc78ecSespie 
1592fddef416Sniklas       if (next_opcode->opcode == 0)
1593fddef416Sniklas 	break;
1594f7cc78ecSespie 
1595fddef416Sniklas       if (strcmp (next_opcode->name, opcode->name))
1596fddef416Sniklas 	break;
1597f7cc78ecSespie 
1598fddef416Sniklas       opcode = next_opcode;
1599fddef416Sniklas     }
1600fddef416Sniklas 
1601fddef416Sniklas   if (!match)
1602fddef416Sniklas     {
1603f7cc78ecSespie       as_bad (_("bad opcode or operands"));
1604fddef416Sniklas       return (0);
1605fddef416Sniklas     }
1606fddef416Sniklas 
16075f210c2aSfgsch   /* Check that all registers that are required to be even are.
16085f210c2aSfgsch      Also, if any operands were marked as registers, but were really symbols,
16095f210c2aSfgsch      fix that here.  */
1610fddef416Sniklas   for (i = 0; opcode->operands[i]; i++)
1611fddef416Sniklas     {
1612fddef416Sniklas       if ((d10v_operands[opcode->operands[i]].flags & OPERAND_EVEN) &&
1613fddef416Sniklas 	  (myops[i].X_add_number & 1))
1614f7cc78ecSespie 	as_fatal (_("Register number must be EVEN"));
1615d2201f2fSdrahn       if ((d10v_operands[opcode->operands[i]].flags & OPERAND_NOSP)
1616d2201f2fSdrahn 	  && (myops[i].X_add_number & OPERAND_SP))
1617d2201f2fSdrahn 	as_bad (_("Unsupported use of sp"));
1618fddef416Sniklas       if (myops[i].X_op == O_register)
1619fddef416Sniklas 	{
1620fddef416Sniklas 	  if (!(d10v_operands[opcode->operands[i]].flags & OPERAND_REG))
1621fddef416Sniklas 	    {
1622fddef416Sniklas 	      myops[i].X_op = O_symbol;
16235f210c2aSfgsch 	      myops[i].X_add_symbol =
16245f210c2aSfgsch 		symbol_find_or_make ((char *) myops[i].X_op_symbol);
1625fddef416Sniklas 	      myops[i].X_add_number = 0;
1626fddef416Sniklas 	      myops[i].X_op_symbol = NULL;
1627fddef416Sniklas 	    }
1628fddef416Sniklas 	}
1629d2201f2fSdrahn       if ((d10v_operands[opcode->operands[i]].flags & OPERAND_CONTROL)
1630d2201f2fSdrahn 	  && (myops[i].X_add_number == OPERAND_CONTROL + 4
1631d2201f2fSdrahn 	      || myops[i].X_add_number == OPERAND_CONTROL + 5
1632d2201f2fSdrahn 	      || myops[i].X_add_number == OPERAND_CONTROL + 6
1633d2201f2fSdrahn 	      || myops[i].X_add_number == OPERAND_CONTROL + 12
1634d2201f2fSdrahn 	      || myops[i].X_add_number == OPERAND_CONTROL + 13
1635d2201f2fSdrahn 	      || myops[i].X_add_number == OPERAND_CONTROL + 15))
1636d2201f2fSdrahn 	as_warn (_("cr%ld is a reserved control register"),
1637d2201f2fSdrahn 		 myops[i].X_add_number - OPERAND_CONTROL);
1638fddef416Sniklas     }
1639fddef416Sniklas   return opcode;
1640fddef416Sniklas }
1641fddef416Sniklas 
16425f210c2aSfgsch /* If while processing a fixup, a reloc really needs to be created.
16435f210c2aSfgsch    Then it is done here.  */
1644fddef416Sniklas 
1645fddef416Sniklas arelent *
tc_gen_reloc(seg,fixp)1646fddef416Sniklas tc_gen_reloc (seg, fixp)
16475f210c2aSfgsch      asection *seg ATTRIBUTE_UNUSED;
1648fddef416Sniklas      fixS *fixp;
1649fddef416Sniklas {
1650fddef416Sniklas   arelent *reloc;
1651fddef416Sniklas   reloc = (arelent *) xmalloc (sizeof (arelent));
1652f7cc78ecSespie   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1653f7cc78ecSespie   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1654fddef416Sniklas   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1655fddef416Sniklas   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1656fddef416Sniklas   if (reloc->howto == (reloc_howto_type *) NULL)
1657fddef416Sniklas     {
1658fddef416Sniklas       as_bad_where (fixp->fx_file, fixp->fx_line,
16595f210c2aSfgsch 		    _("reloc %d not supported by object file format"),
16605f210c2aSfgsch 		    (int) fixp->fx_r_type);
1661fddef416Sniklas       return NULL;
1662fddef416Sniklas     }
1663f7cc78ecSespie 
1664d2201f2fSdrahn   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1665f7cc78ecSespie     reloc->address = fixp->fx_offset;
1666f7cc78ecSespie 
1667d2201f2fSdrahn   reloc->addend = 0;
1668f7cc78ecSespie 
1669fddef416Sniklas   return reloc;
1670fddef416Sniklas }
1671fddef416Sniklas 
1672fddef416Sniklas int
md_estimate_size_before_relax(fragp,seg)1673fddef416Sniklas md_estimate_size_before_relax (fragp, seg)
16745f210c2aSfgsch      fragS *fragp ATTRIBUTE_UNUSED;
16755f210c2aSfgsch      asection *seg ATTRIBUTE_UNUSED;
1676fddef416Sniklas {
1677fddef416Sniklas   abort ();
1678fddef416Sniklas   return 0;
1679fddef416Sniklas }
1680fddef416Sniklas 
1681fddef416Sniklas long
md_pcrel_from_section(fixp,sec)1682fddef416Sniklas md_pcrel_from_section (fixp, sec)
1683fddef416Sniklas      fixS *fixp;
1684fddef416Sniklas      segT sec;
1685fddef416Sniklas {
16865f210c2aSfgsch   if (fixp->fx_addsy != (symbolS *) NULL
16875f210c2aSfgsch       && (!S_IS_DEFINED (fixp->fx_addsy)
16885f210c2aSfgsch 	  || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
1689fddef416Sniklas     return 0;
1690fddef416Sniklas   return fixp->fx_frag->fr_address + fixp->fx_where;
1691fddef416Sniklas }
1692fddef416Sniklas 
1693d2201f2fSdrahn void
md_apply_fix3(fixP,valP,seg)1694d2201f2fSdrahn md_apply_fix3 (fixP, valP, seg)
1695d2201f2fSdrahn      fixS *fixP;
1696d2201f2fSdrahn      valueT *valP;
16975f210c2aSfgsch      segT seg ATTRIBUTE_UNUSED;
1698fddef416Sniklas {
1699fddef416Sniklas   char *where;
1700fddef416Sniklas   unsigned long insn;
1701d2201f2fSdrahn   long value = *valP;
1702fddef416Sniklas   int op_type;
1703fddef416Sniklas   int left = 0;
1704fddef416Sniklas 
1705d2201f2fSdrahn   if (fixP->fx_addsy == (symbolS *) NULL)
1706d2201f2fSdrahn     fixP->fx_done = 1;
1707fddef416Sniklas 
1708d2201f2fSdrahn   /* We don't actually support subtracting a symbol.  */
1709d2201f2fSdrahn   if (fixP->fx_subsy != (symbolS *) NULL)
1710d2201f2fSdrahn     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
1711d2201f2fSdrahn 
1712d2201f2fSdrahn   op_type = fixP->fx_r_type;
1713fddef416Sniklas   if (op_type & 2048)
1714fddef416Sniklas     {
1715fddef416Sniklas       op_type -= 2048;
1716fddef416Sniklas       if (op_type & 1024)
1717fddef416Sniklas 	{
1718fddef416Sniklas 	  op_type -= 1024;
1719d2201f2fSdrahn 	  fixP->fx_r_type = BFD_RELOC_D10V_10_PCREL_L;
1720fddef416Sniklas 	  left = 1;
1721fddef416Sniklas 	}
1722fddef416Sniklas       else if (op_type & 4096)
1723fddef416Sniklas 	{
1724fddef416Sniklas 	  op_type -= 4096;
1725d2201f2fSdrahn 	  fixP->fx_r_type = BFD_RELOC_D10V_18;
1726fddef416Sniklas 	}
1727fddef416Sniklas       else
1728d2201f2fSdrahn 	fixP->fx_r_type =
17295f210c2aSfgsch 	  get_reloc ((struct d10v_operand *) &d10v_operands[op_type]);
1730fddef416Sniklas     }
1731fddef416Sniklas 
1732fddef416Sniklas   /* Fetch the instruction, insert the fully resolved operand
1733fddef416Sniklas      value, and stuff the instruction back again.  */
1734d2201f2fSdrahn   where = fixP->fx_frag->fr_literal + fixP->fx_where;
1735fddef416Sniklas   insn = bfd_getb32 ((unsigned char *) where);
1736fddef416Sniklas 
1737d2201f2fSdrahn   switch (fixP->fx_r_type)
1738fddef416Sniklas     {
1739fddef416Sniklas     case BFD_RELOC_D10V_10_PCREL_L:
1740fddef416Sniklas     case BFD_RELOC_D10V_10_PCREL_R:
1741fddef416Sniklas     case BFD_RELOC_D10V_18_PCREL:
1742d2201f2fSdrahn       /* If the fix is relative to a global symbol, not a section
1743d2201f2fSdrahn 	 symbol, then ignore the offset.
1744d2201f2fSdrahn          XXX - Do we have to worry about branches to a symbol + offset ?  */
1745d2201f2fSdrahn       if (fixP->fx_addsy != NULL
1746d2201f2fSdrahn 	  && S_IS_EXTERN (fixP->fx_addsy) )
1747d2201f2fSdrahn         {
1748d2201f2fSdrahn           segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
1749d2201f2fSdrahn           segment_info_type *segf = seg_info(fseg);
1750d2201f2fSdrahn 
1751d2201f2fSdrahn 	  if ( segf && segf->sym != fixP->fx_addsy)
1752d2201f2fSdrahn 	    value = 0;
1753d2201f2fSdrahn         }
1754d2201f2fSdrahn       /* Drop through.  */
1755fddef416Sniklas     case BFD_RELOC_D10V_18:
17565f210c2aSfgsch       /* Instruction addresses are always right-shifted by 2.  */
1757f7cc78ecSespie       value >>= AT_WORD_RIGHT_SHIFT;
1758d2201f2fSdrahn       if (fixP->fx_size == 2)
1759fddef416Sniklas 	bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
1760fddef416Sniklas       else
1761fddef416Sniklas 	{
1762f7cc78ecSespie 	  struct d10v_opcode *rep, *repi;
1763f7cc78ecSespie 
1764f7cc78ecSespie 	  rep = (struct d10v_opcode *) hash_find (d10v_hash, "rep");
1765f7cc78ecSespie 	  repi = (struct d10v_opcode *) hash_find (d10v_hash, "repi");
1766f7cc78ecSespie 	  if ((insn & FM11) == FM11
1767d2201f2fSdrahn 	      && ((repi != NULL
1768d2201f2fSdrahn 		   && (insn & repi->mask) == (unsigned) repi->opcode)
1769d2201f2fSdrahn 		  || (rep != NULL
1770d2201f2fSdrahn 		      && (insn & rep->mask) == (unsigned) rep->opcode))
1771f7cc78ecSespie 	      && value < 4)
1772f7cc78ecSespie 	    as_fatal
1773f7cc78ecSespie 	      (_("line %d: rep or repi must include at least 4 instructions"),
1774d2201f2fSdrahn 	       fixP->fx_line);
17755f210c2aSfgsch 	  insn =
1776d2201f2fSdrahn 	    d10v_insert_operand (insn, op_type, (offsetT) value, left, fixP);
1777fddef416Sniklas 	  bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1778fddef416Sniklas 	}
1779fddef416Sniklas       break;
1780fddef416Sniklas     case BFD_RELOC_32:
1781fddef416Sniklas       bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
1782fddef416Sniklas       break;
1783fddef416Sniklas     case BFD_RELOC_16:
1784fddef416Sniklas       bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
1785fddef416Sniklas       break;
1786f7cc78ecSespie 
1787f7cc78ecSespie     case BFD_RELOC_VTABLE_INHERIT:
1788f7cc78ecSespie     case BFD_RELOC_VTABLE_ENTRY:
1789d2201f2fSdrahn       fixP->fx_done = 0;
1790d2201f2fSdrahn       return;
1791f7cc78ecSespie 
1792fddef416Sniklas     default:
17935f210c2aSfgsch       as_fatal (_("line %d: unknown relocation type: 0x%x"),
1794d2201f2fSdrahn 		fixP->fx_line, fixP->fx_r_type);
1795fddef416Sniklas     }
1796fddef416Sniklas }
1797fddef416Sniklas 
17985f210c2aSfgsch /* d10v_cleanup() is called after the assembler has finished parsing
17995f210c2aSfgsch    the input file, when a label is read from the input file, or when a
18005f210c2aSfgsch    stab directive is output.  Because the D10V assembler sometimes
18015f210c2aSfgsch    saves short instructions to see if it can package them with the
18025f210c2aSfgsch    next instruction, there may be a short instruction that still needs
18035f210c2aSfgsch    to be written.
18045f210c2aSfgsch 
18055f210c2aSfgsch    NOTE: accesses a global, etype.
18065f210c2aSfgsch    NOTE: invoked by various macros such as md_cleanup: see.  */
18075f210c2aSfgsch 
1808fddef416Sniklas int
d10v_cleanup()1809fddef416Sniklas d10v_cleanup ()
1810fddef416Sniklas {
1811fddef416Sniklas   segT seg;
1812fddef416Sniklas   subsegT subseg;
1813fddef416Sniklas 
18145f210c2aSfgsch   /* If cleanup was invoked because the assembler encountered, e.g., a
18155f210c2aSfgsch      user label, we write out the pending instruction, if any.  If it
18165f210c2aSfgsch      was invoked because the assembler is outputting a piece of line
18175f210c2aSfgsch      debugging information, though, we write out the pending
18185f210c2aSfgsch      instruction only if the --no-gstabs-packing command line switch
18195f210c2aSfgsch      has been specified.  */
18205f210c2aSfgsch   if (prev_opcode
18215f210c2aSfgsch       && etype == PACK_UNSPEC
18225f210c2aSfgsch       && (! outputting_stabs_line_debug || ! flag_allow_gstabs_packing))
1823fddef416Sniklas     {
1824fddef416Sniklas       seg = now_seg;
1825fddef416Sniklas       subseg = now_subseg;
18265f210c2aSfgsch 
1827f7cc78ecSespie       if (prev_seg)
1828fddef416Sniklas 	subseg_set (prev_seg, prev_subseg);
18295f210c2aSfgsch 
1830fddef416Sniklas       write_1_short (prev_opcode, prev_insn, fixups->next);
1831fddef416Sniklas       subseg_set (seg, subseg);
1832fddef416Sniklas       prev_opcode = NULL;
1833fddef416Sniklas     }
1834fddef416Sniklas   return 1;
1835fddef416Sniklas }
1836fddef416Sniklas 
1837d2201f2fSdrahn /* Like normal .word, except support @word.
1838d2201f2fSdrahn    Clobbers input_line_pointer, checks end-of-line.  */
18395f210c2aSfgsch 
1840fddef416Sniklas static void
d10v_dot_word(dummy)18415f210c2aSfgsch d10v_dot_word (dummy)
18425f210c2aSfgsch      int dummy ATTRIBUTE_UNUSED;
1843fddef416Sniklas {
1844fddef416Sniklas   expressionS exp;
1845fddef416Sniklas   char *p;
1846fddef416Sniklas 
1847fddef416Sniklas   if (is_it_end_of_statement ())
1848fddef416Sniklas     {
1849fddef416Sniklas       demand_empty_rest_of_line ();
1850fddef416Sniklas       return;
1851fddef416Sniklas     }
1852fddef416Sniklas 
1853fddef416Sniklas   do
1854fddef416Sniklas     {
1855fddef416Sniklas       expression (&exp);
1856fddef416Sniklas       if (!strncasecmp (input_line_pointer, "@word", 5))
1857fddef416Sniklas 	{
1858fddef416Sniklas 	  exp.X_add_number = 0;
1859fddef416Sniklas 	  input_line_pointer += 5;
1860fddef416Sniklas 
1861fddef416Sniklas 	  p = frag_more (2);
1862fddef416Sniklas 	  fix_new_exp (frag_now, p - frag_now->fr_literal, 2,
1863fddef416Sniklas 		       &exp, 0, BFD_RELOC_D10V_18);
1864fddef416Sniklas 	}
1865fddef416Sniklas       else
1866fddef416Sniklas 	emit_expr (&exp, 2);
1867fddef416Sniklas     }
1868fddef416Sniklas   while (*input_line_pointer++ == ',');
1869fddef416Sniklas 
1870fddef416Sniklas   input_line_pointer--;		/* Put terminator back into stream.  */
1871fddef416Sniklas   demand_empty_rest_of_line ();
1872fddef416Sniklas }
1873fddef416Sniklas 
18745f210c2aSfgsch /* Mitsubishi asked that we support some old syntax that apparently
18755f210c2aSfgsch    had immediate operands starting with '#'.  This is in some of their
18765f210c2aSfgsch    sample code but is not documented (although it appears in some
18775f210c2aSfgsch    examples in their assembler manual). For now, we'll solve this
18785f210c2aSfgsch    compatibility problem by simply ignoring any '#' at the beginning
18795f210c2aSfgsch    of an operand.  */
1880fddef416Sniklas 
1881d2201f2fSdrahn /* Operands that begin with '#' should fall through to here.
1882d2201f2fSdrahn    From expr.c.  */
1883fddef416Sniklas 
1884fddef416Sniklas void
md_operand(expressionP)1885fddef416Sniklas md_operand (expressionP)
1886fddef416Sniklas      expressionS *expressionP;
1887fddef416Sniklas {
1888f7cc78ecSespie   if (*input_line_pointer == '#' && ! do_not_ignore_hash)
1889fddef416Sniklas     {
1890fddef416Sniklas       input_line_pointer++;
1891fddef416Sniklas       expression (expressionP);
1892fddef416Sniklas     }
1893fddef416Sniklas }
1894fddef416Sniklas 
1895d2201f2fSdrahn bfd_boolean
d10v_fix_adjustable(fixP)1896f7cc78ecSespie d10v_fix_adjustable (fixP)
1897f7cc78ecSespie      fixS *fixP;
1898f7cc78ecSespie {
18995f210c2aSfgsch   /* We need the symbol name for the VTABLE entries.  */
1900f7cc78ecSespie   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1901f7cc78ecSespie       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1902f7cc78ecSespie     return 0;
1903f7cc78ecSespie 
1904f7cc78ecSespie   return 1;
1905f7cc78ecSespie }
1906