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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-mn10200.c] - Blame information for rev 299

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 16 khays
/* 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 163 khays
          break;
485 16 khays
        case 0xe8:
486
          opcode = 0xe9;
487
          break;
488
        case 0xe9:
489
          opcode = 0xe8;
490
          break;
491
        case 0xe0:
492
          opcode = 0xe2;
493
          break;
494
        case 0xe2:
495
          opcode = 0xe0;
496
          break;
497
        case 0xe3:
498
          opcode = 0xe1;
499
          break;
500
        case 0xe1:
501
          opcode = 0xe3;
502
          break;
503
        case 0xe4:
504
          opcode = 0xe6;
505
          break;
506
        case 0xe6:
507
          opcode = 0xe4;
508
          break;
509
        case 0xe7:
510
          opcode = 0xe5;
511
          break;
512
        case 0xe5:
513
          opcode = 0xe7;
514
          break;
515
        case 0xec:
516
          opcode = 0xed;
517
          break;
518
        case 0xed:
519
          opcode = 0xec;
520
          break;
521
        case 0xee:
522
          opcode = 0xef;
523
          break;
524
        case 0xef:
525
          opcode = 0xee;
526
          break;
527
        default:
528
          abort ();
529
        }
530
      fragP->fr_literal[offset + 1] = opcode;
531
 
532
      /* Create a fixup for the reversed conditional branch.  */
533
      sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
534
      fix_new (fragP, fragP->fr_fix + 2, 1,
535
               symbol_new (buf, sec, 0, fragP->fr_next),
536
               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
537
 
538
      /* Now create the unconditional branch + fixup to the
539
         final target.  */
540
      fragP->fr_literal[offset + 3] = 0xfc;
541
      fix_new (fragP, fragP->fr_fix + 4, 2, fragP->fr_symbol,
542
               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
543
      fragP->fr_var = 0;
544
      fragP->fr_fix += 6;
545
    }
546
  else if (fragP->fr_subtype == 5)
547
    {
548
      /* Reverse the condition of the first branch.  */
549
      int offset = fragP->fr_fix;
550
      int opcode = fragP->fr_literal[offset + 1] & 0xff;
551
 
552
      switch (opcode)
553
        {
554
        case 0xfc:
555
          opcode = 0xfd;
556
          break;
557
        case 0xfd:
558
          opcode = 0xfc;
559
          break;
560
        case 0xfe:
561
          opcode = 0xff;
562
          break;
563
        case 0xff:
564
          opcode = 0xfe;
565
        case 0xe8:
566
          opcode = 0xe9;
567
          break;
568
        case 0xe9:
569
          opcode = 0xe8;
570
          break;
571
        case 0xe0:
572
          opcode = 0xe2;
573
          break;
574
        case 0xe2:
575
          opcode = 0xe0;
576
          break;
577
        case 0xe3:
578
          opcode = 0xe1;
579
          break;
580
        case 0xe1:
581
          opcode = 0xe3;
582
          break;
583
        case 0xe4:
584
          opcode = 0xe6;
585
          break;
586
        case 0xe6:
587
          opcode = 0xe4;
588
          break;
589
        case 0xe7:
590
          opcode = 0xe5;
591
          break;
592
        case 0xe5:
593
          opcode = 0xe7;
594
          break;
595
        case 0xec:
596
          opcode = 0xed;
597
          break;
598
        case 0xed:
599
          opcode = 0xec;
600
          break;
601
        case 0xee:
602
          opcode = 0xef;
603
          break;
604
        case 0xef:
605
          opcode = 0xee;
606
          break;
607
        default:
608
          abort ();
609
        }
610
      fragP->fr_literal[offset + 1] = opcode;
611
 
612
      /* Create a fixup for the reversed conditional branch.  */
613
      sprintf (buf, ".%s_%ld", FAKE_LABEL_NAME, label_count++);
614
      fix_new (fragP, fragP->fr_fix + 2, 1,
615
               symbol_new (buf, sec, 0, fragP->fr_next),
616
               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
617
 
618
      /* Now create the unconditional branch + fixup to the
619
         final target.  */
620
      fragP->fr_literal[offset + 3] = 0xf4;
621
      fragP->fr_literal[offset + 4] = 0xe0;
622
      fix_new (fragP, fragP->fr_fix + 5, 4, fragP->fr_symbol,
623
               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
624
      fragP->fr_var = 0;
625
      fragP->fr_fix += 8;
626
    }
627
  else if (fragP->fr_subtype == 6)
628
    {
629
      fix_new (fragP, fragP->fr_fix + 1, 2, fragP->fr_symbol,
630
               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
631
      fragP->fr_var = 0;
632
      fragP->fr_fix += 3;
633
    }
634
  else if (fragP->fr_subtype == 7)
635
    {
636
      int offset = fragP->fr_fix;
637
      fragP->fr_literal[offset] = 0xf4;
638
      fragP->fr_literal[offset + 1] = 0xe1;
639
 
640
      fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
641
               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
642
      fragP->fr_var = 0;
643
      fragP->fr_fix += 5;
644
    }
645
  else if (fragP->fr_subtype == 8)
646
    {
647
      fragP->fr_literal[fragP->fr_fix] = 0xea;
648
      fix_new (fragP, fragP->fr_fix + 1, 1, fragP->fr_symbol,
649
               fragP->fr_offset, 1, BFD_RELOC_8_PCREL);
650
      fragP->fr_var = 0;
651
      fragP->fr_fix += 2;
652
    }
653
  else if (fragP->fr_subtype == 9)
654
    {
655
      int offset = fragP->fr_fix;
656
      fragP->fr_literal[offset] = 0xfc;
657
 
658
      fix_new (fragP, fragP->fr_fix + 1, 4, fragP->fr_symbol,
659
               fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
660
      fragP->fr_var = 0;
661
      fragP->fr_fix += 3;
662
    }
663
  else if (fragP->fr_subtype == 10)
664
    {
665
      int offset = fragP->fr_fix;
666
      fragP->fr_literal[offset] = 0xf4;
667
      fragP->fr_literal[offset + 1] = 0xe0;
668
 
669
      fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
670
               fragP->fr_offset, 1, BFD_RELOC_24_PCREL);
671
      fragP->fr_var = 0;
672
      fragP->fr_fix += 5;
673
    }
674
  else
675
    abort ();
676
}
677
 
678
valueT
679
md_section_align (asection *seg, valueT addr)
680
{
681
  int align = bfd_get_section_alignment (stdoutput, seg);
682
  return ((addr + (1 << align) - 1) & (-1 << align));
683
}
684
 
685
void
686
md_begin (void)
687
{
688
  char *prev_name = "";
689
  register const struct mn10200_opcode *op;
690
 
691
  mn10200_hash = hash_new ();
692
 
693
  /* Insert unique names into hash table.  The MN10200 instruction set
694
     has many identical opcode names that have different opcodes based
695
     on the operands.  This hash table then provides a quick index to
696
     the first opcode with a particular name in the opcode table.  */
697
 
698
  op = mn10200_opcodes;
699
  while (op->name)
700
    {
701
      if (strcmp (prev_name, op->name))
702
        {
703
          prev_name = (char *) op->name;
704
          hash_insert (mn10200_hash, op->name, (char *) op);
705
        }
706
      op++;
707
    }
708
 
709
  /* This is both a simplification (we don't have to write md_apply_fix)
710
     and support for future optimizations (branch shortening and similar
711
     stuff in the linker.  */
712
  linkrelax = 1;
713
}
714
 
715
static unsigned long
716
check_operand (unsigned long insn ATTRIBUTE_UNUSED,
717
               const struct mn10200_operand *operand,
718
               offsetT val)
719
{
720
  /* No need to check 24bit or 32bit operands for a bit.  */
721
  if (operand->bits < 24
722
      && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
723
    {
724
      long min, max;
725
      offsetT test;
726
 
727
      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
728
        {
729
          max = (1 << (operand->bits - 1)) - 1;
730
          min = - (1 << (operand->bits - 1));
731
        }
732
      else
733
        {
734
          max = (1 << operand->bits) - 1;
735
          min = 0;
736
        }
737
 
738
      test = val;
739
 
740
      if (test < (offsetT) min || test > (offsetT) max)
741
        return 0;
742
      else
743
        return 1;
744
    }
745
  return 1;
746
}
747
/* If while processing a fixup, a reloc really needs to be created
748
   Then it is done here.  */
749
 
750
arelent *
751
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
752
{
753
  arelent *reloc;
754
  reloc = xmalloc (sizeof (arelent));
755
 
756
  if (fixp->fx_subsy != NULL)
757
    {
758
      if (S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)
759
          && S_IS_DEFINED (fixp->fx_subsy))
760
        {
761
          fixp->fx_offset -= S_GET_VALUE (fixp->fx_subsy);
762
          fixp->fx_subsy = NULL;
763
        }
764
      else
765
        /* FIXME: We should try more ways to resolve difference expressions
766
           here.  At least this is better than silently ignoring the
767
           subtrahend.  */
768
        as_bad_where (fixp->fx_file, fixp->fx_line,
769
                      _("can't resolve `%s' {%s section} - `%s' {%s section}"),
770
                      fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
771
                      segment_name (fixp->fx_addsy
772
                                    ? S_GET_SEGMENT (fixp->fx_addsy)
773
                                    : absolute_section),
774
                      S_GET_NAME (fixp->fx_subsy),
775
                      segment_name (S_GET_SEGMENT (fixp->fx_addsy)));
776
    }
777
 
778
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
779
  if (reloc->howto == NULL)
780
    {
781
      as_bad_where (fixp->fx_file, fixp->fx_line,
782
                    _("reloc %d not supported by object file format"),
783
                    (int) fixp->fx_r_type);
784
      return NULL;
785
    }
786
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
787
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
788
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
789
  reloc->addend = fixp->fx_offset;
790
  return reloc;
791
}
792
 
793
int
794
md_estimate_size_before_relax (fragS *fragp, asection *seg)
795
{
796
  if (fragp->fr_subtype == 6
797
      && (!S_IS_DEFINED (fragp->fr_symbol)
798
          || seg != S_GET_SEGMENT (fragp->fr_symbol)))
799
    fragp->fr_subtype = 7;
800
  else if (fragp->fr_subtype == 8
801
           && (!S_IS_DEFINED (fragp->fr_symbol)
802
               || seg != S_GET_SEGMENT (fragp->fr_symbol)))
803
    fragp->fr_subtype = 10;
804
 
805
  if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
806
    abort ();
807
 
808
  return md_relax_table[fragp->fr_subtype].rlx_length;
809
}
810
 
811
long
812
md_pcrel_from (fixS *fixp)
813
{
814
  return fixp->fx_frag->fr_address;
815
}
816
 
817
void
818
md_apply_fix (fixS * fixP, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
819
{
820
  /* We shouldn't ever get here because linkrelax is nonzero.  */
821
  abort ();
822
  fixP->fx_done = 1;
823
}
824
 
825
/* Insert an operand value into an instruction.  */
826
 
827
static void
828
mn10200_insert_operand (unsigned long *insnp,
829
                        unsigned long *extensionp,
830
                        const struct mn10200_operand *operand,
831
                        offsetT val,
832
                        char *file,
833
                        unsigned int line,
834
                        unsigned int shift)
835
{
836
  /* No need to check 24 or 32bit operands for a bit.  */
837
  if (operand->bits < 24
838
      && (operand->flags & MN10200_OPERAND_NOCHECK) == 0)
839
    {
840
      long min, max;
841
      offsetT test;
842
 
843
      if ((operand->flags & MN10200_OPERAND_SIGNED) != 0)
844
        {
845
          max = (1 << (operand->bits - 1)) - 1;
846
          min = - (1 << (operand->bits - 1));
847
        }
848
      else
849
        {
850
          max = (1 << operand->bits) - 1;
851
          min = 0;
852
        }
853
 
854
      test = val;
855
 
856
      if (test < (offsetT) min || test > (offsetT) max)
857
        as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
858
    }
859
 
860
  if ((operand->flags & MN10200_OPERAND_EXTENDED) == 0)
861
    {
862
      *insnp |= (((long) val & ((1 << operand->bits) - 1))
863
                 << (operand->shift + shift));
864
 
865
      if ((operand->flags & MN10200_OPERAND_REPEATED) != 0)
866
        *insnp |= (((long) val & ((1 << operand->bits) - 1))
867
                   << (operand->shift + shift + 2));
868
    }
869
  else
870
    {
871
      *extensionp |= (val >> 16) & 0xff;
872
      *insnp |= val & 0xffff;
873
    }
874
}
875
 
876
void
877
md_assemble (char *str)
878
{
879
  char *s;
880
  struct mn10200_opcode *opcode;
881
  struct mn10200_opcode *next_opcode;
882
  const unsigned char *opindex_ptr;
883
  int next_opindex, relaxable;
884
  unsigned long insn, extension, size = 0;
885
  char *f;
886
  int i;
887
  int match;
888
 
889
  /* Get the opcode.  */
890
  for (s = str; *s != '\0' && !ISSPACE (*s); s++)
891
    ;
892
  if (*s != '\0')
893
    *s++ = '\0';
894
 
895
  /* Find the first opcode with the proper name.  */
896
  opcode = (struct mn10200_opcode *) hash_find (mn10200_hash, str);
897
  if (opcode == NULL)
898
    {
899
      as_bad (_("Unrecognized opcode: `%s'"), str);
900
      return;
901
    }
902
 
903
  str = s;
904
  while (ISSPACE (*str))
905
    ++str;
906
 
907
  input_line_pointer = str;
908
 
909
  for (;;)
910
    {
911
      const char *errmsg = NULL;
912
      int op_idx;
913
      char *hold;
914
      int extra_shift = 0;
915
 
916
      relaxable = 0;
917
      fc = 0;
918
      match = 0;
919
      next_opindex = 0;
920
      insn = opcode->opcode;
921
      extension = 0;
922
      for (op_idx = 1, opindex_ptr = opcode->operands;
923
           *opindex_ptr != 0;
924
           opindex_ptr++, op_idx++)
925
        {
926
          const struct mn10200_operand *operand;
927
          expressionS ex;
928
 
929
          if (next_opindex == 0)
930
            {
931
              operand = &mn10200_operands[*opindex_ptr];
932
            }
933
          else
934
            {
935
              operand = &mn10200_operands[next_opindex];
936
              next_opindex = 0;
937
            }
938
 
939
          errmsg = NULL;
940
 
941
          while (*str == ' ' || *str == ',')
942
            ++str;
943
 
944
          if (operand->flags & MN10200_OPERAND_RELAX)
945
            relaxable = 1;
946
 
947
          /* Gather the operand.  */
948
          hold = input_line_pointer;
949
          input_line_pointer = str;
950
 
951
          if (operand->flags & MN10200_OPERAND_PAREN)
952
            {
953
              if (*input_line_pointer != ')' && *input_line_pointer != '(')
954
                {
955
                  input_line_pointer = hold;
956
                  str = hold;
957
                  goto error;
958
                }
959
              input_line_pointer++;
960
              goto keep_going;
961
            }
962
          /* See if we can match the operands.  */
963
          else if (operand->flags & MN10200_OPERAND_DREG)
964
            {
965
              if (!data_register_name (&ex))
966
                {
967
                  input_line_pointer = hold;
968
                  str = hold;
969
                  goto error;
970
                }
971
            }
972
          else if (operand->flags & MN10200_OPERAND_AREG)
973
            {
974
              if (!address_register_name (&ex))
975
                {
976
                  input_line_pointer = hold;
977
                  str = hold;
978
                  goto error;
979
                }
980
            }
981
          else if (operand->flags & MN10200_OPERAND_PSW)
982
            {
983
              char *start = input_line_pointer;
984
              char c = get_symbol_end ();
985
 
986
              if (strcmp (start, "psw") != 0)
987
                {
988
                  *input_line_pointer = c;
989
                  input_line_pointer = hold;
990
                  str = hold;
991
                  goto error;
992
                }
993
              *input_line_pointer = c;
994
              goto keep_going;
995
            }
996
          else if (operand->flags & MN10200_OPERAND_MDR)
997
            {
998
              char *start = input_line_pointer;
999
              char c = get_symbol_end ();
1000
 
1001
              if (strcmp (start, "mdr") != 0)
1002
                {
1003
                  *input_line_pointer = c;
1004
                  input_line_pointer = hold;
1005
                  str = hold;
1006
                  goto error;
1007
                }
1008
              *input_line_pointer = c;
1009
              goto keep_going;
1010
            }
1011
          else if (data_register_name (&ex))
1012
            {
1013
              input_line_pointer = hold;
1014
              str = hold;
1015
              goto error;
1016
            }
1017
          else if (address_register_name (&ex))
1018
            {
1019
              input_line_pointer = hold;
1020
              str = hold;
1021
              goto error;
1022
            }
1023
          else if (other_register_name (&ex))
1024
            {
1025
              input_line_pointer = hold;
1026
              str = hold;
1027
              goto error;
1028
            }
1029
          else if (*str == ')' || *str == '(')
1030
            {
1031
              input_line_pointer = hold;
1032
              str = hold;
1033
              goto error;
1034
            }
1035
          else
1036
            {
1037
              expression (&ex);
1038
            }
1039
 
1040
          switch (ex.X_op)
1041
            {
1042
            case O_illegal:
1043
              errmsg = _("illegal operand");
1044
              goto error;
1045
            case O_absent:
1046
              errmsg = _("missing operand");
1047
              goto error;
1048
            case O_register:
1049
              if ((operand->flags
1050
                   & (MN10200_OPERAND_DREG | MN10200_OPERAND_AREG)) == 0)
1051
                {
1052
                  input_line_pointer = hold;
1053
                  str = hold;
1054
                  goto error;
1055
                }
1056
 
1057
              if (opcode->format == FMT_2 || opcode->format == FMT_5)
1058
                extra_shift = 8;
1059
              else if (opcode->format == FMT_3 || opcode->format == FMT_6
1060
                       || opcode->format == FMT_7)
1061
                extra_shift = 16;
1062
              else
1063
                extra_shift = 0;
1064
 
1065
              mn10200_insert_operand (&insn, &extension, operand,
1066
                                      ex.X_add_number, NULL,
1067
                                      0, extra_shift);
1068
 
1069
              break;
1070
 
1071
            case O_constant:
1072
              /* If this operand can be promoted, and it doesn't
1073
                 fit into the allocated bitfield for this insn,
1074
                 then promote it (ie this opcode does not match).  */
1075
              if (operand->flags
1076
                  & (MN10200_OPERAND_PROMOTE | MN10200_OPERAND_RELAX)
1077
                  && !check_operand (insn, operand, ex.X_add_number))
1078
                {
1079
                  input_line_pointer = hold;
1080
                  str = hold;
1081
                  goto error;
1082
                }
1083
 
1084
              mn10200_insert_operand (&insn, &extension, operand,
1085
                                      ex.X_add_number, NULL,
1086
                                      0, 0);
1087
              break;
1088
 
1089
            default:
1090
              /* If this operand can be promoted, then this opcode didn't
1091
                 match since we can't know if it needed promotion!  */
1092
              if (operand->flags & MN10200_OPERAND_PROMOTE)
1093
                {
1094
                  input_line_pointer = hold;
1095
                  str = hold;
1096
                  goto error;
1097
                }
1098
 
1099
              /* We need to generate a fixup for this expression.  */
1100
              if (fc >= MAX_INSN_FIXUPS)
1101
                as_fatal (_("too many fixups"));
1102
              fixups[fc].exp = ex;
1103
              fixups[fc].opindex = *opindex_ptr;
1104
              fixups[fc].reloc = BFD_RELOC_UNUSED;
1105
              ++fc;
1106
              break;
1107
            }
1108
 
1109
keep_going:
1110
          str = input_line_pointer;
1111
          input_line_pointer = hold;
1112
 
1113
          while (*str == ' ' || *str == ',')
1114
            ++str;
1115
 
1116
        }
1117
 
1118
      /* Make sure we used all the operands!  */
1119
      if (*str != ',')
1120
        match = 1;
1121
 
1122
    error:
1123
      if (match == 0)
1124
        {
1125
          next_opcode = opcode + 1;
1126
          if (!strcmp (next_opcode->name, opcode->name))
1127
            {
1128
              opcode = next_opcode;
1129
              continue;
1130
            }
1131
 
1132
          as_bad ("%s", errmsg);
1133
          return;
1134
        }
1135
      break;
1136
    }
1137
 
1138
  while (ISSPACE (*str))
1139
    ++str;
1140
 
1141
  if (*str != '\0')
1142
    as_bad (_("junk at end of line: `%s'"), str);
1143
 
1144
  input_line_pointer = str;
1145
 
1146
  if (opcode->format == FMT_1)
1147
    size = 1;
1148
  else if (opcode->format == FMT_2 || opcode->format == FMT_4)
1149
    size = 2;
1150
  else if (opcode->format == FMT_3 || opcode->format == FMT_5)
1151
    size = 3;
1152
  else if (opcode->format == FMT_6)
1153
    size = 4;
1154
  else if (opcode->format == FMT_7)
1155
    size = 5;
1156
  else
1157
    abort ();
1158
 
1159
  /* Write out the instruction.  */
1160
  dwarf2_emit_insn (0);
1161
  if (relaxable && fc > 0)
1162
    {
1163
      /* On a 64-bit host the size of an 'int' is not the same
1164
         as the size of a pointer, so we need a union to convert
1165
         the opindex field of the fr_cgen structure into a char *
1166
         so that it can be stored in the frag.  We do not have
1167
         to worry about loosing accuracy as we are not going to
1168
         be even close to the 32bit limit of the int.  */
1169
      union
1170
      {
1171
        int opindex;
1172
        char * ptr;
1173
      }
1174
      opindex_converter;
1175
      int type;
1176
 
1177
      /* bCC  */
1178
      if (size == 2 && opcode->opcode != 0xfc0000)
1179
        {
1180
          /* Handle bra specially.  Basically treat it like jmp so
1181
             that we automatically handle 8, 16 and 32 bit offsets
1182
             correctly as well as jumps to an undefined address.
1183
 
1184
             It is also important to not treat it like other bCC
1185
             instructions since the long forms of bra is different
1186
             from other bCC instructions.  */
1187
          if (opcode->opcode == 0xea00)
1188
            type = 8;
1189
          else
1190
            type = 0;
1191
        }
1192
      /* jsr  */
1193
      else if (size == 3 && opcode->opcode == 0xfd0000)
1194
        type = 6;
1195
      /* jmp  */
1196
      else if (size == 3 && opcode->opcode == 0xfc0000)
1197
        type = 8;
1198
      /* bCCx  */
1199
      else
1200
        type = 3;
1201
 
1202
      opindex_converter.opindex = fixups[0].opindex;
1203
      f = frag_var (rs_machine_dependent, 8, 8 - size, type,
1204
                    fixups[0].exp.X_add_symbol,
1205
                    fixups[0].exp.X_add_number,
1206
                    opindex_converter.ptr);
1207
      number_to_chars_bigendian (f, insn, size);
1208
      if (8 - size > 4)
1209
        {
1210
          number_to_chars_bigendian (f + size, 0, 4);
1211
          number_to_chars_bigendian (f + size + 4, 0, 8 - size - 4);
1212
        }
1213
      else
1214
        number_to_chars_bigendian (f + size, 0, 8 - size);
1215
    }
1216
  else
1217
    {
1218
      f = frag_more (size);
1219
 
1220
      /* Oh, what a mess.  The instruction is in big endian format, but
1221
         16 and 24bit immediates are little endian!  */
1222
      if (opcode->format == FMT_3)
1223
        {
1224
          number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
1225
          number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
1226
        }
1227
      else if (opcode->format == FMT_6)
1228
        {
1229
          number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1230
          number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1231
        }
1232
      else if (opcode->format == FMT_7)
1233
        {
1234
          number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
1235
          number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
1236
          number_to_chars_littleendian (f + 4, extension & 0xff, 1);
1237
        }
1238
      else
1239
        number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
1240
 
1241
      /* Create any fixups.  */
1242
      for (i = 0; i < fc; i++)
1243
        {
1244
          const struct mn10200_operand *operand;
1245
          int reloc_size;
1246
 
1247
          operand = &mn10200_operands[fixups[i].opindex];
1248
          if (fixups[i].reloc != BFD_RELOC_UNUSED)
1249
            {
1250
              reloc_howto_type *reloc_howto;
1251
              int offset;
1252
              fixS *fixP;
1253
 
1254
              reloc_howto = bfd_reloc_type_lookup (stdoutput,
1255
                                                   fixups[i].reloc);
1256
 
1257
              if (!reloc_howto)
1258
                abort ();
1259
 
1260
              reloc_size = bfd_get_reloc_size (reloc_howto);
1261
 
1262
              if (reloc_size < 1 || reloc_size > 4)
1263
                abort ();
1264
 
1265
              offset = 4 - reloc_size;
1266
              fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1267
                                  reloc_size,
1268
                                  &fixups[i].exp,
1269
                                  reloc_howto->pc_relative,
1270
                                  fixups[i].reloc);
1271
 
1272
              /* PC-relative offsets are from the first byte of the
1273
                 next instruction, not from the start of the current
1274
                 instruction.  */
1275
              if (reloc_howto->pc_relative)
1276
                fixP->fx_offset += reloc_size;
1277
            }
1278
          else
1279
            {
1280
              int reloc, pcrel, offset;
1281
              fixS *fixP;
1282
 
1283
              reloc = BFD_RELOC_NONE;
1284
              /* How big is the reloc?  Remember SPLIT relocs are
1285
                 implicitly 32bits.  */
1286
              reloc_size = operand->bits;
1287
 
1288
              offset = size - reloc_size / 8;
1289
 
1290
              /* Is the reloc pc-relative?  */
1291
              pcrel = (operand->flags & MN10200_OPERAND_PCREL) != 0;
1292
 
1293
              /* Choose a proper BFD relocation type.  */
1294
              if (pcrel)
1295
                {
1296
                  if (reloc_size == 8)
1297
                    reloc = BFD_RELOC_8_PCREL;
1298
                  else if (reloc_size == 24)
1299
                    reloc = BFD_RELOC_24_PCREL;
1300
                  else
1301
                    abort ();
1302
                }
1303
              else
1304
                {
1305
                  if (reloc_size == 32)
1306
                    reloc = BFD_RELOC_32;
1307
                  else if (reloc_size == 16)
1308
                    reloc = BFD_RELOC_16;
1309
                  else if (reloc_size == 8)
1310
                    reloc = BFD_RELOC_8;
1311
                  else if (reloc_size == 24)
1312
                    reloc = BFD_RELOC_24;
1313
                  else
1314
                    abort ();
1315
                }
1316
 
1317
              /* Convert the size of the reloc into what fix_new_exp
1318
                 wants.  */
1319
              reloc_size = reloc_size / 8;
1320
              if (reloc_size == 8)
1321
                reloc_size = 0;
1322
              else if (reloc_size == 16)
1323
                reloc_size = 1;
1324
              else if (reloc_size == 32 || reloc_size == 24)
1325
                reloc_size = 2;
1326
 
1327
              fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
1328
                                  reloc_size, &fixups[i].exp, pcrel,
1329
                                  ((bfd_reloc_code_real_type) reloc));
1330
 
1331
              /* PC-relative offsets are from the first byte of the
1332
                 next instruction, not from the start of the current
1333
                 instruction.  */
1334
              if (pcrel)
1335
                fixP->fx_offset += size;
1336
            }
1337
        }
1338
    }
1339
}
1340
 

powered by: WebSVN 2.1.0

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