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