]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-mn10200.c
gas/testsuite/
[thirdparty/binutils-gdb.git] / gas / config / tc-mn10200.c
CommitLineData
252b5132 1/* tc-mn10200.c -- Assembler code for the Matsushita 10200
ea1562b3 2 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
8ad7c533 3 2005, 2006 Free Software Foundation, Inc.
252b5132
RH
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
4b4da160
NC
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "as.h"
3882b010 23#include "safe-ctype.h"
87271fa6 24#include "subsegs.h"
252b5132
RH
25#include "opcode/mn10200.h"
26\f
27/* Structure to hold information about predefined registers. */
28struct reg_name
29{
30 const char *name;
31 int value;
32};
33
87271fa6
NC
34/* Generic assembler global variables which must be defined by all
35 targets. */
252b5132 36
87271fa6 37/* Characters which always start a comment. */
252b5132
RH
38const char comment_chars[] = "#";
39
40/* Characters which start a comment at the beginning of a line. */
41const char line_comment_chars[] = ";#";
42
87271fa6 43/* Characters which may be used to separate multiple commands on a
252b5132
RH
44 single line. */
45const char line_separator_chars[] = ";";
46
87271fa6 47/* Characters which are used to indicate an exponent in a floating
252b5132
RH
48 point number. */
49const char EXP_CHARS[] = "eE";
50
87271fa6 51/* Characters which mean that a number is a floating point constant,
252b5132
RH
52 as in 0d1.0. */
53const char FLT_CHARS[] = "dD";
54\f
ea1562b3
NC
55const relax_typeS md_relax_table[] =
56 {
87271fa6 57 /* bCC relaxing */
252b5132
RH
58 {0x81, -0x7e, 2, 1},
59 {0x8004, -0x7ffb, 5, 2},
60 {0x800006, -0x7ffff9, 7, 0},
87271fa6 61 /* bCCx relaxing */
252b5132
RH
62 {0x81, -0x7e, 3, 4},
63 {0x8004, -0x7ffb, 6, 5},
64 {0x800006, -0x7ffff9, 8, 0},
87271fa6 65 /* jsr relaxing */
252b5132
RH
66 {0x8004, -0x7ffb, 3, 7},
67 {0x800006, -0x7ffff9, 5, 0},
87271fa6 68 /* jmp relaxing */
252b5132
RH
69 {0x81, -0x7e, 2, 9},
70 {0x8004, -0x7ffb, 3, 10},
71 {0x800006, -0x7ffff9, 5, 0},
72
73};
87271fa6 74
252b5132 75
87271fa6 76/* Fixups. */
ea1562b3
NC
77#define MAX_INSN_FIXUPS 5
78
252b5132
RH
79struct mn10200_fixup
80{
81 expressionS exp;
82 int opindex;
83 bfd_reloc_code_real_type reloc;
84};
ea1562b3 85
252b5132
RH
86struct mn10200_fixup fixups[MAX_INSN_FIXUPS];
87static int fc;
88\f
89const char *md_shortopts = "";
ea1562b3
NC
90
91struct option md_longopts[] =
92{
252b5132
RH
93 {NULL, no_argument, NULL, 0}
94};
ea1562b3 95
87271fa6 96size_t md_longopts_size = sizeof (md_longopts);
252b5132
RH
97
98/* The target specific pseudo-ops which we support. */
99const pseudo_typeS md_pseudo_table[] =
100{
101 { NULL, NULL, 0 }
102};
103
104/* Opcode hash table. */
105static struct hash_control *mn10200_hash;
106
87271fa6 107/* This table is sorted. Suitable for searching by a binary search. */
252b5132
RH
108static const struct reg_name data_registers[] =
109{
110 { "d0", 0 },
111 { "d1", 1 },
112 { "d2", 2 },
113 { "d3", 3 },
114};
87271fa6
NC
115#define DATA_REG_NAME_CNT \
116 (sizeof (data_registers) / sizeof (struct reg_name))
252b5132
RH
117
118static const struct reg_name address_registers[] =
119{
120 { "a0", 0 },
121 { "a1", 1 },
122 { "a2", 2 },
123 { "a3", 3 },
124};
87271fa6
NC
125#define ADDRESS_REG_NAME_CNT \
126 (sizeof (address_registers) / sizeof (struct reg_name))
252b5132
RH
127
128static const struct reg_name other_registers[] =
129{
130 { "mdr", 0 },
131 { "psw", 0 },
132};
87271fa6
NC
133#define OTHER_REG_NAME_CNT \
134 (sizeof (other_registers) / sizeof (struct reg_name))
252b5132
RH
135
136/* reg_name_search does a binary search of the given register table
137 to see if "name" is a valid regiter name. Returns the register
87271fa6 138 number from the array on success, or -1 on failure. */
252b5132
RH
139
140static int
ea1562b3
NC
141reg_name_search (const struct reg_name *regs,
142 int regcount,
143 const char *name)
252b5132
RH
144{
145 int middle, low, high;
146 int cmp;
147
148 low = 0;
149 high = regcount - 1;
150
151 do
152 {
153 middle = (low + high) / 2;
154 cmp = strcasecmp (name, regs[middle].name);
155 if (cmp < 0)
156 high = middle - 1;
157 else if (cmp > 0)
158 low = middle + 1;
87271fa6
NC
159 else
160 return regs[middle].value;
252b5132
RH
161 }
162 while (low <= high);
163 return -1;
164}
165
252b5132 166/* Summary of register_name().
ea1562b3
NC
167
168 in: Input_line_pointer points to 1st char of operand.
169
170 out: An expressionS.
171 The operand may have been a register: in this case, X_op == O_register,
172 X_add_number is set to the register number, and truth is returned.
173 Input_line_pointer->(next non-blank) char after operand, or is in
174 its original state. */
87271fa6 175
b34976b6 176static bfd_boolean
ea1562b3 177data_register_name (expressionS *expressionP)
252b5132
RH
178{
179 int reg_number;
180 char *name;
181 char *start;
182 char c;
183
87271fa6 184 /* Find the spelling of the operand. */
252b5132
RH
185 start = name = input_line_pointer;
186
187 c = get_symbol_end ();
188 reg_number = reg_name_search (data_registers, DATA_REG_NAME_CNT, name);
189
468cced8
AM
190 /* Put back the delimiting char. */
191 *input_line_pointer = c;
192
87271fa6
NC
193 /* Look to see if it's in the register table. */
194 if (reg_number >= 0)
252b5132
RH
195 {
196 expressionP->X_op = O_register;
197 expressionP->X_add_number = reg_number;
198
87271fa6 199 /* Make the rest nice. */
252b5132
RH
200 expressionP->X_add_symbol = NULL;
201 expressionP->X_op_symbol = NULL;
87271fa6 202
b34976b6 203 return TRUE;
252b5132 204 }
87271fa6 205
468cced8
AM
206 /* Reset the line as if we had not done anything. */
207 input_line_pointer = start;
b34976b6 208 return FALSE;
252b5132
RH
209}
210
211/* Summary of register_name().
ea1562b3
NC
212
213 in: Input_line_pointer points to 1st char of operand.
214
215 out: An expressionS.
216 The operand may have been a register: in this case, X_op == O_register,
217 X_add_number is set to the register number, and truth is returned.
218 Input_line_pointer->(next non-blank) char after operand, or is in
219 its original state. */
87271fa6 220
b34976b6 221static bfd_boolean
ea1562b3 222address_register_name (expressionS *expressionP)
252b5132
RH
223{
224 int reg_number;
225 char *name;
226 char *start;
227 char c;
228
87271fa6 229 /* Find the spelling of the operand. */
252b5132
RH
230 start = name = input_line_pointer;
231
232 c = get_symbol_end ();
233 reg_number = reg_name_search (address_registers, ADDRESS_REG_NAME_CNT, name);
234
468cced8
AM
235 /* Put back the delimiting char. */
236 *input_line_pointer = c;
237
87271fa6
NC
238 /* Look to see if it's in the register table. */
239 if (reg_number >= 0)
252b5132
RH
240 {
241 expressionP->X_op = O_register;
242 expressionP->X_add_number = reg_number;
243
87271fa6 244 /* Make the rest nice. */
252b5132
RH
245 expressionP->X_add_symbol = NULL;
246 expressionP->X_op_symbol = NULL;
87271fa6 247
b34976b6 248 return TRUE;
252b5132 249 }
87271fa6 250
468cced8
AM
251 /* Reset the line as if we had not done anything. */
252 input_line_pointer = start;
b34976b6 253 return FALSE;
252b5132
RH
254}
255
256/* Summary of register_name().
ea1562b3
NC
257
258 in: Input_line_pointer points to 1st char of operand.
259
260 out: An expressionS.
261 The operand may have been a register: in this case, X_op == O_register,
262 X_add_number is set to the register number, and truth is returned.
263 Input_line_pointer->(next non-blank) char after operand, or is in
264 its original state. */
87271fa6 265
b34976b6 266static bfd_boolean
ea1562b3 267other_register_name (expressionS *expressionP)
252b5132
RH
268{
269 int reg_number;
270 char *name;
271 char *start;
272 char c;
273
87271fa6 274 /* Find the spelling of the operand. */
252b5132
RH
275 start = name = input_line_pointer;
276
277 c = get_symbol_end ();
278 reg_number = reg_name_search (other_registers, OTHER_REG_NAME_CNT, name);
279
468cced8
AM
280 /* Put back the delimiting char. */
281 *input_line_pointer = c;
282
87271fa6
NC
283 /* Look to see if it's in the register table. */
284 if (reg_number >= 0)
252b5132
RH
285 {
286 expressionP->X_op = O_register;
287 expressionP->X_add_number = reg_number;
288
87271fa6 289 /* Make the rest nice. */
252b5132
RH
290 expressionP->X_add_symbol = NULL;
291 expressionP->X_op_symbol = NULL;
87271fa6 292
b34976b6 293 return TRUE;
252b5132 294 }
87271fa6 295
468cced8
AM
296 /* Reset the line as if we had not done anything. */
297 input_line_pointer = start;
b34976b6 298 return FALSE;
252b5132
RH
299}
300
301void
ea1562b3 302md_show_usage (FILE *stream)
252b5132 303{
87271fa6 304 fprintf (stream, _("MN10200 options:\n\
252b5132 305none yet\n"));
87271fa6 306}
252b5132
RH
307
308int
ea1562b3
NC
309md_parse_option (int c ATTRIBUTE_UNUSED,
310 char *arg ATTRIBUTE_UNUSED)
252b5132
RH
311{
312 return 0;
313}
314
315symbolS *
ea1562b3 316md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
252b5132
RH
317{
318 return 0;
319}
320
321char *
ea1562b3 322md_atof (int type, char *litp, int *sizep)
252b5132
RH
323{
324 int prec;
325 LITTLENUM_TYPE words[4];
326 char *t;
327 int i;
328
329 switch (type)
330 {
331 case 'f':
332 prec = 2;
333 break;
334
335 case 'd':
336 prec = 4;
337 break;
338
339 default:
340 *sizep = 0;
341 return _("bad call to md_atof");
342 }
87271fa6 343
252b5132
RH
344 t = atof_ieee (input_line_pointer, type, words);
345 if (t)
346 input_line_pointer = t;
347
348 *sizep = prec * 2;
349
350 for (i = prec - 1; i >= 0; i--)
351 {
352 md_number_to_chars (litp, (valueT) words[i], 2);
353 litp += 2;
354 }
355
356 return NULL;
357}
358
252b5132 359void
ea1562b3
NC
360md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
361 asection *sec,
362 fragS *fragP)
252b5132
RH
363{
364 static unsigned long label_count = 0;
365 char buf[40];
366
367 subseg_change (sec, 0);
368 if (fragP->fr_subtype == 0)
369 {
370 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
371 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
372 fragP->fr_var = 0;
373 fragP->fr_fix += 2;
374 }
375 else if (fragP->fr_subtype == 1)
376 {
377 /* Reverse the condition of the first branch. */
378 int offset = fragP->fr_fix;
379 int opcode = fragP->fr_literal[offset] & 0xff;
380
381 switch (opcode)
382 {
383 case 0xe8:
384 opcode = 0xe9;
385 break;
386 case 0xe9:
387 opcode = 0xe8;
388 break;
389 case 0xe0:
390 opcode = 0xe2;
391 break;
392 case 0xe2:
393 opcode = 0xe0;
394 break;
395 case 0xe3:
396 opcode = 0xe1;
397 break;
398 case 0xe1:
399 opcode = 0xe3;
400 break;
401 case 0xe4:
402 opcode = 0xe6;
403 break;
404 case 0xe6:
405 opcode = 0xe4;
406 break;
407 case 0xe7:
408 opcode = 0xe5;
409 break;
410 case 0xe5:
411 opcode = 0xe7;
412 break;
413 default:
414 abort ();
415 }
416 fragP->fr_literal[offset] = opcode;
417
418 /* Create a fixup for the reversed conditional branch. */
2a8ce8da 419 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
252b5132
RH
420 fix_new (fragP, fragP->fr_fix + 1, 1,
421 symbol_new (buf, sec, 0, fragP->fr_next),
422 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
423
424 /* Now create the unconditional branch + fixup to the
425 final target. */
426 fragP->fr_literal[offset + 2] = 0xfc;
427 fix_new (fragP, fragP->fr_fix + 3, 2, fragP->fr_symbol,
428 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
429 fragP->fr_var = 0;
430 fragP->fr_fix += 5;
431 }
432 else if (fragP->fr_subtype == 2)
433 {
434 /* Reverse the condition of the first branch. */
435 int offset = fragP->fr_fix;
436 int opcode = fragP->fr_literal[offset] & 0xff;
437
438 switch (opcode)
439 {
440 case 0xe8:
441 opcode = 0xe9;
442 break;
443 case 0xe9:
444 opcode = 0xe8;
445 break;
446 case 0xe0:
447 opcode = 0xe2;
448 break;
449 case 0xe2:
450 opcode = 0xe0;
451 break;
452 case 0xe3:
453 opcode = 0xe1;
454 break;
455 case 0xe1:
456 opcode = 0xe3;
457 break;
458 case 0xe4:
459 opcode = 0xe6;
460 break;
461 case 0xe6:
462 opcode = 0xe4;
463 break;
464 case 0xe7:
465 opcode = 0xe5;
466 break;
467 case 0xe5:
468 opcode = 0xe7;
469 break;
470 default:
471 abort ();
472 }
473 fragP->fr_literal[offset] = opcode;
474
475 /* Create a fixup for the reversed conditional branch. */
2a8ce8da 476 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
252b5132
RH
477 fix_new (fragP, fragP->fr_fix + 1, 1,
478 symbol_new (buf, sec, 0, fragP->fr_next),
479 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
480
481 /* Now create the unconditional branch + fixup to the
482 final target. */
483 fragP->fr_literal[offset + 2] = 0xf4;
484 fragP->fr_literal[offset + 3] = 0xe0;
485 fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
486 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
487 fragP->fr_var = 0;
488 fragP->fr_fix += 7;
489 }
490 else if (fragP->fr_subtype == 3)
491 {
492 fix_new (fragP, fragP->fr_fix + 2, 1, fragP->fr_symbol,
493 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
494 fragP->fr_var = 0;
495 fragP->fr_fix += 3;
496 }
497 else if (fragP->fr_subtype == 4)
498 {
499 /* Reverse the condition of the first branch. */
500 int offset = fragP->fr_fix;
501 int opcode = fragP->fr_literal[offset + 1] & 0xff;
502
503 switch (opcode)
504 {
505 case 0xfc:
506 opcode = 0xfd;
507 break;
508 case 0xfd:
509 opcode = 0xfc;
510 break;
511 case 0xfe:
512 opcode = 0xff;
513 break;
514 case 0xff:
515 opcode = 0xfe;
516 case 0xe8:
517 opcode = 0xe9;
518 break;
519 case 0xe9:
520 opcode = 0xe8;
521 break;
522 case 0xe0:
523 opcode = 0xe2;
524 break;
525 case 0xe2:
526 opcode = 0xe0;
527 break;
528 case 0xe3:
529 opcode = 0xe1;
530 break;
531 case 0xe1:
532 opcode = 0xe3;
533 break;
534 case 0xe4:
535 opcode = 0xe6;
536 break;
537 case 0xe6:
538 opcode = 0xe4;
539 break;
540 case 0xe7:
541 opcode = 0xe5;
542 break;
543 case 0xe5:
544 opcode = 0xe7;
545 break;
546 case 0xec:
547 opcode = 0xed;
548 break;
549 case 0xed:
550 opcode = 0xec;
551 break;
552 case 0xee:
553 opcode = 0xef;
554 break;
555 case 0xef:
556 opcode = 0xee;
557 break;
558 default:
559 abort ();
560 }
561 fragP->fr_literal[offset + 1] = opcode;
562
563 /* Create a fixup for the reversed conditional branch. */
2a8ce8da 564 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
252b5132
RH
565 fix_new (fragP, fragP->fr_fix + 2, 1,
566 symbol_new (buf, sec, 0, fragP->fr_next),
567 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
568
569 /* Now create the unconditional branch + fixup to the
570 final target. */
571 fragP->fr_literal[offset + 3] = 0xfc;
572 fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
573 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
574 fragP->fr_var = 0;
575 fragP->fr_fix += 6;
576 }
577 else if (fragP->fr_subtype == 5)
578 {
579 /* Reverse the condition of the first branch. */
580 int offset = fragP->fr_fix;
581 int opcode = fragP->fr_literal[offset + 1] & 0xff;
582
583 switch (opcode)
584 {
585 case 0xfc:
586 opcode = 0xfd;
587 break;
588 case 0xfd:
589 opcode = 0xfc;
590 break;
591 case 0xfe:
592 opcode = 0xff;
593 break;
594 case 0xff:
595 opcode = 0xfe;
596 case 0xe8:
597 opcode = 0xe9;
598 break;
599 case 0xe9:
600 opcode = 0xe8;
601 break;
602 case 0xe0:
603 opcode = 0xe2;
604 break;
605 case 0xe2:
606 opcode = 0xe0;
607 break;
608 case 0xe3:
609 opcode = 0xe1;
610 break;
611 case 0xe1:
612 opcode = 0xe3;
613 break;
614 case 0xe4:
615 opcode = 0xe6;
616 break;
617 case 0xe6:
618 opcode = 0xe4;
619 break;
620 case 0xe7:
621 opcode = 0xe5;
622 break;
623 case 0xe5:
624 opcode = 0xe7;
625 break;
626 case 0xec:
627 opcode = 0xed;
628 break;
629 case 0xed:
630 opcode = 0xec;
631 break;
632 case 0xee:
633 opcode = 0xef;
634 break;
635 case 0xef:
636 opcode = 0xee;
637 break;
638 default:
639 abort ();
640 }
641 fragP->fr_literal[offset + 1] = opcode;
642
643 /* Create a fixup for the reversed conditional branch. */
2a8ce8da 644 sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
252b5132
RH
645 fix_new (fragP, fragP->fr_fix + 2, 1,
646 symbol_new (buf, sec, 0, fragP->fr_next),
647 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
648
649 /* Now create the unconditional branch + fixup to the
650 final target. */
651 fragP->fr_literal[offset + 3] = 0xf4;
652 fragP->fr_literal[offset + 4] = 0xe0;
653 fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
654 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
655 fragP->fr_var = 0;
656 fragP->fr_fix += 8;
657 }
658 else if (fragP->fr_subtype == 6)
659 {
660 fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
661 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
662 fragP->fr_var = 0;
663 fragP->fr_fix += 3;
664 }
665 else if (fragP->fr_subtype == 7)
666 {
667 int offset = fragP->fr_fix;
668 fragP->fr_literal[offset] = 0xf4;
669 fragP->fr_literal[offset + 1] = 0xe1;
670
671 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
672 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
673 fragP->fr_var = 0;
674 fragP->fr_fix += 5;
675 }
676 else if (fragP->fr_subtype == 8)
677 {
678 fragP->fr_literal[fragP->fr_fix] = 0xea;
679 fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
680 fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
681 fragP->fr_var = 0;
682 fragP->fr_fix += 2;
683 }
684 else if (fragP->fr_subtype == 9)
685 {
686 int offset = fragP->fr_fix;
687 fragP->fr_literal[offset] = 0xfc;
688
689 fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
690 fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
691 fragP->fr_var = 0;
692 fragP->fr_fix += 3;
693 }
694 else if (fragP->fr_subtype == 10)
695 {
696 int offset = fragP->fr_fix;
697 fragP->fr_literal[offset] = 0xf4;
698 fragP->fr_literal[offset + 1] = 0xe0;
699
700 fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
701 fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
702 fragP->fr_var = 0;
703 fragP->fr_fix += 5;
704 }
705 else
706 abort ();
707}
708
709valueT
ea1562b3 710md_section_align (asection *seg, valueT addr)
252b5132
RH
711{
712 int align = bfd_get_section_alignment (stdoutput, seg);
713 return ((addr + (1 << align) - 1) & (-1 << align));
714}
715
716void
ea1562b3 717md_begin (void)
252b5132
RH
718{
719 char *prev_name = "";
720 register const struct mn10200_opcode *op;
721
87271fa6 722 mn10200_hash = hash_new ();
252b5132
RH
723
724 /* Insert unique names into hash table. The MN10200 instruction set
725 has many identical opcode names that have different opcodes based
726 on the operands. This hash table then provides a quick index to
727 the first opcode with a particular name in the opcode table. */
728
729 op = mn10200_opcodes;
730 while (op->name)
731 {
87271fa6 732 if (strcmp (prev_name, op->name))
252b5132
RH
733 {
734 prev_name = (char *) op->name;
735 hash_insert (mn10200_hash, op->name, (char *) op);
736 }
737 op++;
738 }
739
55cf6793 740 /* This is both a simplification (we don't have to write md_apply_fix)
252b5132
RH
741 and support for future optimizations (branch shortening and similar
742 stuff in the linker. */
743 linkrelax = 1;
744}
745
ea1562b3
NC
746static unsigned long
747check_operand (unsigned long insn ATTRIBUTE_UNUSED,
748 const struct mn10200_operand *operand,
749 offsetT val)
750{
751 /* No need to check 24bit or 32bit operands for a bit. */
752 if (operand->bits < 24
753 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
754 {
755 long min, max;
756 offsetT test;
757
758 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
759 {
760 max = (1 << (operand->bits - 1)) - 1;
761 min = - (1 << (operand->bits - 1));
762 }
763 else
764 {
765 max = (1 << operand->bits) - 1;
766 min = 0;
767 }
768
769 test = val;
770
771 if (test < (offsetT) min || test > (offsetT) max)
772 return 0;
773 else
774 return 1;
775 }
776 return 1;
777}
778/* If while processing a fixup, a reloc really needs to be created
779 Then it is done here. */
780
781arelent *
782tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
783{
784 arelent *reloc;
785 reloc = xmalloc (sizeof (arelent));
786
787 if (fixp->fx_subsy != NULL)
788 {
789 if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
790 && S_IS_DEFINED (fixp->fx_subsy))
791 {
792 fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
793 fixp->fx_subsy = NULL;
794 }
795 else
796 /* FIXME: We should try more ways to resolve difference expressions
797 here. At least this is better than silently ignoring the
798 subtrahend. */
799 as_bad_where (fixp->fx_file, fixp->fx_line,
800 _("can't resolve `%s' {%s section} - `%s' {%s section}"),
801 fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
802 segment_name (fixp->fx_addsy
803 ? S_GET_SEGMENT (fixp->fx_addsy)
804 : absolute_section),
805 S_GET_NAME (fixp->fx_subsy),
806 segment_name (S_GET_SEGMENT (fixp->fx_addsy)));
807 }
808
809 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
810 if (reloc->howto == NULL)
811 {
812 as_bad_where (fixp->fx_file, fixp->fx_line,
813 _("reloc %d not supported by object file format"),
814 (int) fixp->fx_r_type);
815 return NULL;
816 }
817 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
818 reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
819 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
820 reloc->addend = fixp->fx_offset;
821 return reloc;
822}
823
824int
825md_estimate_size_before_relax (fragS *fragp, asection *seg)
826{
827 if (fragp->fr_subtype == 6
828 && (!S_IS_DEFINED (fragp->fr_symbol)
829 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
830 fragp->fr_subtype = 7;
831 else if (fragp->fr_subtype == 8
832 && (!S_IS_DEFINED (fragp->fr_symbol)
833 || seg != S_GET_SEGMENT (fragp->fr_symbol)))
834 fragp->fr_subtype = 10;
835
836 if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
837 abort ();
838
839 return md_relax_table[fragp->fr_subtype].rlx_length;
840}
841
842long
843md_pcrel_from (fixS *fixp)
844{
845 return fixp->fx_frag->fr_address;
846}
847
252b5132 848void
55cf6793 849md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
ea1562b3
NC
850{
851 /* We shouldn't ever get here because linkrelax is nonzero. */
852 abort ();
853 fixP->fx_done = 1;
854}
855
856/* Insert an operand value into an instruction. */
857
858static void
859mn10200_insert_operand (unsigned long *insnp,
860 unsigned long *extensionp,
861 const struct mn10200_operand *operand,
862 offsetT val,
863 char *file,
864 unsigned int line,
865 unsigned int shift)
866{
867 /* No need to check 24 or 32bit operands for a bit. */
868 if (operand->bits < 24
869 && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
870 {
871 long min, max;
872 offsetT test;
873
874 if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
875 {
876 max = (1 << (operand->bits - 1)) - 1;
877 min = - (1 << (operand->bits - 1));
878 }
879 else
880 {
881 max = (1 << operand->bits) - 1;
882 min = 0;
883 }
884
885 test = val;
886
887 if (test < (offsetT) min || test > (offsetT) max)
888 as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
889 }
890
891 if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
892 {
893 *insnp |= (((long) val & ((1 << operand->bits) - 1))
894 << (operand->shift + shift));
895
896 if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
897 *insnp |= (((long) val & ((1 << operand->bits) - 1))
898 << (operand->shift + shift + 2));
899 }
900 else
901 {
902 *extensionp |= (val >> 16) & 0xff;
903 *insnp |= val & 0xffff;
904 }
905}
906
907void
908md_assemble (char *str)
252b5132
RH
909{
910 char *s;
911 struct mn10200_opcode *opcode;
912 struct mn10200_opcode *next_opcode;
913 const unsigned char *opindex_ptr;
914 int next_opindex, relaxable;
915 unsigned long insn, extension, size = 0;
916 char *f;
917 int i;
918 int match;
919
920 /* Get the opcode. */
3882b010 921 for (s = str; *s != '\0' && !ISSPACE (*s); s++)
252b5132
RH
922 ;
923 if (*s != '\0')
924 *s++ = '\0';
925
87271fa6
NC
926 /* Find the first opcode with the proper name. */
927 opcode = (struct mn10200_opcode *) hash_find (mn10200_hash, str);
252b5132
RH
928 if (opcode == NULL)
929 {
930 as_bad (_("Unrecognized opcode: `%s'"), str);
931 return;
932 }
933
934 str = s;
3882b010 935 while (ISSPACE (*str))
252b5132
RH
936 ++str;
937
938 input_line_pointer = str;
939
87271fa6 940 for (;;)
252b5132
RH
941 {
942 const char *errmsg = NULL;
943 int op_idx;
944 char *hold;
945 int extra_shift = 0;
946
947 relaxable = 0;
948 fc = 0;
949 match = 0;
950 next_opindex = 0;
951 insn = opcode->opcode;
952 extension = 0;
953 for (op_idx = 1, opindex_ptr = opcode->operands;
954 *opindex_ptr != 0;
955 opindex_ptr++, op_idx++)
956 {
957 const struct mn10200_operand *operand;
958 expressionS ex;
959
960 if (next_opindex == 0)
961 {
962 operand = &mn10200_operands[*opindex_ptr];
963 }
964 else
965 {
966 operand = &mn10200_operands[next_opindex];
967 next_opindex = 0;
968 }
969
970 errmsg = NULL;
971
972 while (*str == ' ' || *str == ',')
973 ++str;
974
975 if (operand->flags & MN10200_OPERAND_RELAX)
976 relaxable = 1;
977
87271fa6 978 /* Gather the operand. */
252b5132
RH
979 hold = input_line_pointer;
980 input_line_pointer = str;
981
982 if (operand->flags & MN10200_OPERAND_PAREN)
983 {
984 if (*input_line_pointer != ')' && *input_line_pointer != '(')
985 {
986 input_line_pointer = hold;
987 str = hold;
988 goto error;
989 }
990 input_line_pointer++;
991 goto keep_going;
992 }
993 /* See if we can match the operands. */
994 else if (operand->flags & MN10200_OPERAND_DREG)
995 {
996 if (!data_register_name (&ex))
997 {
998 input_line_pointer = hold;
999 str = hold;
1000 goto error;
1001 }
1002 }
1003 else if (operand->flags & MN10200_OPERAND_AREG)
1004 {
1005 if (!address_register_name (&ex))
1006 {
1007 input_line_pointer = hold;
1008 str = hold;
1009 goto error;
1010 }
1011 }
1012 else if (operand->flags & MN10200_OPERAND_PSW)
1013 {
1014 char *start = input_line_pointer;
1015 char c = get_symbol_end ();
1016
1017 if (strcmp (start, "psw") != 0)
1018 {
1019 *input_line_pointer = c;
1020 input_line_pointer = hold;
1021 str = hold;
1022 goto error;
1023 }
1024 *input_line_pointer = c;
1025 goto keep_going;
1026 }
1027 else if (operand->flags & MN10200_OPERAND_MDR)
1028 {
1029 char *start = input_line_pointer;
1030 char c = get_symbol_end ();
1031
1032 if (strcmp (start, "mdr") != 0)
1033 {
1034 *input_line_pointer = c;
1035 input_line_pointer = hold;
1036 str = hold;
1037 goto error;
1038 }
1039 *input_line_pointer = c;
1040 goto keep_going;
1041 }
1042 else if (data_register_name (&ex))
1043 {
1044 input_line_pointer = hold;
1045 str = hold;
1046 goto error;
1047 }
1048 else if (address_register_name (&ex))
1049 {
1050 input_line_pointer = hold;
1051 str = hold;
1052 goto error;
1053 }
1054 else if (other_register_name (&ex))
1055 {
1056 input_line_pointer = hold;
1057 str = hold;
1058 goto error;
1059 }
1060 else if (*str == ')' || *str == '(')
1061 {
1062 input_line_pointer = hold;
1063 str = hold;
1064 goto error;
1065 }
1066 else
1067 {
1068 expression (&ex);
1069 }
1070
87271fa6 1071 switch (ex.X_op)
252b5132
RH
1072 {
1073 case O_illegal:
1074 errmsg = _("illegal operand");
1075 goto error;
1076 case O_absent:
1077 errmsg = _("missing operand");
1078 goto error;
1079 case O_register:
1080 if ((operand->flags
87271fa6 1081 & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
252b5132
RH
1082 {
1083 input_line_pointer = hold;
1084 str = hold;
1085 goto error;
1086 }
87271fa6 1087
252b5132
RH
1088 if (opcode->format == FMT_2 || opcode->format == FMT_5)
1089 extra_shift = 8;
1090 else if (opcode->format == FMT_3 || opcode->format == FMT_6
1091 || opcode->format == FMT_7)
1092 extra_shift = 16;
1093 else
1094 extra_shift = 0;
87271fa6 1095
252b5132 1096 mn10200_insert_operand (&insn, &extension, operand,
ea1562b3 1097 ex.X_add_number, NULL,
252b5132
RH
1098 0, extra_shift);
1099
1100 break;
1101
1102 case O_constant:
1103 /* If this operand can be promoted, and it doesn't
1104 fit into the allocated bitfield for this insn,
1105 then promote it (ie this opcode does not match). */
1106 if (operand->flags
1107 & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
87271fa6 1108 && !check_operand (insn, operand, ex.X_add_number))
252b5132
RH
1109 {
1110 input_line_pointer = hold;
1111 str = hold;
1112 goto error;
1113 }
1114
1115 mn10200_insert_operand (&insn, &extension, operand,
ea1562b3 1116 ex.X_add_number, NULL,
252b5132
RH
1117 0, 0);
1118 break;
1119
1120 default:
1121 /* If this operand can be promoted, then this opcode didn't
1122 match since we can't know if it needed promotion! */
1123 if (operand->flags & MN10200_OPERAND_PROMOTE)
1124 {
1125 input_line_pointer = hold;
1126 str = hold;
1127 goto error;
1128 }
1129
1130 /* We need to generate a fixup for this expression. */
1131 if (fc >= MAX_INSN_FIXUPS)
1132 as_fatal (_("too many fixups"));
1133 fixups[fc].exp = ex;
1134 fixups[fc].opindex = *opindex_ptr;
1135 fixups[fc].reloc = BFD_RELOC_UNUSED;
1136 ++fc;
1137 break;
1138 }
1139
1140keep_going:
1141 str = input_line_pointer;
1142 input_line_pointer = hold;
1143
1144 while (*str == ' ' || *str == ',')
1145 ++str;
1146
1147 }
1148
1149 /* Make sure we used all the operands! */
1150 if (*str != ',')
1151 match = 1;
1152
1153 error:
1154 if (match == 0)
87271fa6 1155 {
252b5132 1156 next_opcode = opcode + 1;
87271fa6 1157 if (!strcmp (next_opcode->name, opcode->name))
252b5132
RH
1158 {
1159 opcode = next_opcode;
1160 continue;
1161 }
87271fa6 1162
252b5132
RH
1163 as_bad ("%s", errmsg);
1164 return;
87271fa6 1165 }
252b5132
RH
1166 break;
1167 }
87271fa6 1168
3882b010 1169 while (ISSPACE (*str))
252b5132
RH
1170 ++str;
1171
1172 if (*str != '\0')
1173 as_bad (_("junk at end of line: `%s'"), str);
1174
1175 input_line_pointer = str;
1176
1177 if (opcode->format == FMT_1)
1178 size = 1;
1179 else if (opcode->format == FMT_2 || opcode->format == FMT_4)
1180 size = 2;
1181 else if (opcode->format == FMT_3 || opcode->format == FMT_5)
1182 size = 3;
1183 else if (opcode->format == FMT_6)
1184 size = 4;
1185 else if (opcode->format == FMT_7)
1186 size = 5;
1187 else
1188 abort ();
87271fa6 1189
252b5132 1190 /* Write out the instruction. */
252b5132
RH
1191 if (relaxable && fc > 0)
1192 {
8ad7c533
NC
1193 /* On a 64-bit host the size of an 'int' is not the same
1194 as the size of a pointer, so we need a union to convert
1195 the opindex field of the fr_cgen structure into a char *
1196 so that it can be stored in the frag. We do not have
1197 to worry about loosing accuracy as we are not going to
1198 be even close to the 32bit limit of the int. */
1199 union
1200 {
1201 int opindex;
1202 char * ptr;
1203 }
1204 opindex_converter;
252b5132
RH
1205 int type;
1206
87271fa6 1207 /* bCC */
252b5132
RH
1208 if (size == 2 && opcode->opcode != 0xfc0000)
1209 {
1210 /* Handle bra specially. Basically treat it like jmp so
1211 that we automatically handle 8, 16 and 32 bit offsets
1212 correctly as well as jumps to an undefined address.
1213
1214 It is also important to not treat it like other bCC
1215 instructions since the long forms of bra is different
1216 from other bCC instructions. */
87271fa6
NC
1217 if (opcode->opcode == 0xea00)
1218 type = 8;
252b5132
RH
1219 else
1220 type = 0;
1221 }
87271fa6 1222 /* jsr */
252b5132
RH
1223 else if (size == 3 && opcode->opcode == 0xfd0000)
1224 type = 6;
87271fa6 1225 /* jmp */
252b5132
RH
1226 else if (size == 3 && opcode->opcode == 0xfc0000)
1227 type = 8;
87271fa6 1228 /* bCCx */
252b5132
RH
1229 else
1230 type = 3;
1231
8ad7c533 1232 opindex_converter.opindex = fixups[0].opindex;
252b5132
RH
1233 f = frag_var (rs_machine_dependent, 8, 8 - size, type,
1234 fixups[0].exp.X_add_symbol,
1235 fixups[0].exp.X_add_number,
8ad7c533 1236 opindex_converter.ptr);
252b5132
RH
1237 number_to_chars_bigendian (f, insn, size);
1238 if (8 - size > 4)
1239 {
1240 number_to_chars_bigendian (f + size, 0, 4);
1241 number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
1242 }
1243 else
1244 number_to_chars_bigendian (f + size, 0, 8 - size);
1245 }
252b5132
RH
1246 else
1247 {
1248 f = frag_more (size);
1249
1250 /* Oh, what a mess. The instruction is in big endian format, but
1251 16 and 24bit immediates are little endian! */
1252 if (opcode->format == FMT_3)
1253 {
1254 number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
1255 number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
1256 }
1257 else if (opcode->format == FMT_6)
1258 {
1259 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1260 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1261 }
1262 else if (opcode->format == FMT_7)
1263 {
1264 number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1265 number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1266 number_to_chars_littleendian (f + 4, extension & 0xff, 1);
1267 }
1268 else
ea1562b3 1269 number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
252b5132
RH
1270
1271 /* Create any fixups. */
1272 for (i = 0; i < fc; i++)
1273 {
1274 const struct mn10200_operand *operand;
1275
1276 operand = &mn10200_operands[fixups[i].opindex];
1277 if (fixups[i].reloc != BFD_RELOC_UNUSED)
1278 {
1279 reloc_howto_type *reloc_howto;
1280 int size;
1281 int offset;
1282 fixS *fixP;
1283
87271fa6
NC
1284 reloc_howto = bfd_reloc_type_lookup (stdoutput,
1285 fixups[i].reloc);
252b5132
RH
1286
1287 if (!reloc_howto)
87271fa6
NC
1288 abort ();
1289
252b5132
RH
1290 size = bfd_get_reloc_size (reloc_howto);
1291
1292 if (size < 1 || size > 4)
87271fa6 1293 abort ();
252b5132
RH
1294
1295 offset = 4 - size;
1296 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1297 size,
87271fa6 1298 &fixups[i].exp,
252b5132
RH
1299 reloc_howto->pc_relative,
1300 fixups[i].reloc);
1301
87271fa6
NC
1302 /* PC-relative offsets are from the first byte of the
1303 next instruction, not from the start of the current
1304 instruction. */
252b5132
RH
1305 if (reloc_howto->pc_relative)
1306 fixP->fx_offset += size;
1307 }
1308 else
1309 {
1310 int reloc, pcrel, reloc_size, offset;
1311 fixS *fixP;
1312
1313 reloc = BFD_RELOC_NONE;
1314 /* How big is the reloc? Remember SPLIT relocs are
1315 implicitly 32bits. */
1316 reloc_size = operand->bits;
1317
1318 offset = size - reloc_size / 8;
1319
1320 /* Is the reloc pc-relative? */
1321 pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
1322
252b5132
RH
1323 /* Choose a proper BFD relocation type. */
1324 if (pcrel)
1325 {
1326 if (reloc_size == 8)
1327 reloc = BFD_RELOC_8_PCREL;
1328 else if (reloc_size == 24)
1329 reloc = BFD_RELOC_24_PCREL;
1330 else
1331 abort ();
1332 }
1333 else
1334 {
1335 if (reloc_size == 32)
1336 reloc = BFD_RELOC_32;
1337 else if (reloc_size == 16)
1338 reloc = BFD_RELOC_16;
1339 else if (reloc_size == 8)
1340 reloc = BFD_RELOC_8;
1341 else if (reloc_size == 24)
1342 reloc = BFD_RELOC_24;
1343 else
1344 abort ();
1345 }
1346
87271fa6
NC
1347 /* Convert the size of the reloc into what fix_new_exp
1348 wants. */
252b5132
RH
1349 reloc_size = reloc_size / 8;
1350 if (reloc_size == 8)
1351 reloc_size = 0;
1352 else if (reloc_size == 16)
1353 reloc_size = 1;
1354 else if (reloc_size == 32 || reloc_size == 24)
1355 reloc_size = 2;
1356
1357 fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1358 reloc_size, &fixups[i].exp, pcrel,
1359 ((bfd_reloc_code_real_type) reloc));
1360
87271fa6
NC
1361 /* PC-relative offsets are from the first byte of the
1362 next instruction, not from the start of the current
1363 instruction. */
252b5132
RH
1364 if (pcrel)
1365 fixP->fx_offset += size;
1366 }
1367 }
1368 }
1369}
1370