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