OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-mn10200.c] - Blame information for rev 205

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.