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