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