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