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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-mt.c] - Blame information for rev 853

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

Line No. Rev Author Line
1 38 julius
/* tc-mt.c -- Assembler for the Morpho Technologies mt .
2
   Copyright (C) 2005, 2006, 2007 Free Software Foundation.
3
 
4
   This file is part of GAS, the GNU Assembler.
5
 
6
   GAS is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
 
11
   GAS is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with GAS; see the file COPYING.  If not, write to
18
   the Free Software Foundation, 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20
 
21
#include "as.h"
22
#include "dwarf2dbg.h"
23
#include "subsegs.h"     
24
#include "symcat.h"
25
#include "opcodes/mt-desc.h"
26
#include "opcodes/mt-opc.h"
27
#include "cgen.h"
28
#include "elf/common.h"
29
#include "elf/mt.h"
30
#include "libbfd.h"
31
 
32
/* Structure to hold all of the different components
33
   describing an individual instruction.  */
34
typedef struct
35
{
36
  const CGEN_INSN *     insn;
37
  const CGEN_INSN *     orig_insn;
38
  CGEN_FIELDS           fields;
39
#if CGEN_INT_INSN_P
40
  CGEN_INSN_INT         buffer [1];
41
#define INSN_VALUE(buf) (*(buf))
42
#else
43
  unsigned char         buffer [CGEN_MAX_INSN_SIZE];
44
#define INSN_VALUE(buf) (buf)
45
#endif
46
  char *                addr;
47
  fragS *               frag;
48
  int                   num_fixups;
49
  fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
50
  int                   indices [MAX_OPERAND_INSTANCES];
51
}
52
mt_insn;
53
 
54
 
55
const char comment_chars[]        = ";";
56
const char line_comment_chars[]   = "#";
57
const char line_separator_chars[] = "";
58
const char EXP_CHARS[]            = "eE";
59
const char FLT_CHARS[]            = "dD";
60
 
61
/* The target specific pseudo-ops which we support.  */
62
const pseudo_typeS md_pseudo_table[] =
63
{
64
    { "word",   cons,                   4 },
65
    { NULL,     NULL,                   0 }
66
};
67
 
68
 
69
 
70
static int no_scheduling_restrictions = 0;
71
 
72
struct option md_longopts[] =
73
{
74
#define OPTION_NO_SCHED_REST    (OPTION_MD_BASE)
75
  { "nosched",     no_argument, NULL, OPTION_NO_SCHED_REST },
76
#define OPTION_MARCH            (OPTION_MD_BASE + 1)
77
  { "march", required_argument, NULL, OPTION_MARCH},
78
  { NULL,          no_argument, NULL, 0 },
79
};
80
size_t md_longopts_size = sizeof (md_longopts);
81
 
82
const char * md_shortopts = "";
83
 
84
/* Mach selected from command line.  */
85
static int mt_mach = bfd_mach_ms1;
86
static unsigned mt_mach_bitmask = 1 << MACH_MS1;
87
 
88
/* Flags to set in the elf header */
89
static flagword mt_flags = EF_MT_CPU_MRISC;
90
 
91
/* The architecture to use.  */
92
enum mt_architectures
93
  {
94
    ms1_64_001,
95
    ms1_16_002,
96
    ms1_16_003,
97
    ms2
98
  };
99
 
100
/* MT architecture we are using for this output file.  */
101
static enum mt_architectures mt_arch = ms1_16_002;
102
 
103
int
104
md_parse_option (int c ATTRIBUTE_UNUSED, char * arg)
105
{
106
  switch (c)
107
    {
108
    case OPTION_MARCH:
109
      if (strcmp (arg, "ms1-64-001") == 0)
110
        {
111
          mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
112
          mt_mach = bfd_mach_ms1;
113
          mt_mach_bitmask = 1 << MACH_MS1;
114
          mt_arch = ms1_64_001;
115
        }
116
      else if (strcmp (arg, "ms1-16-002") == 0)
117
        {
118
          mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC;
119
          mt_mach = bfd_mach_ms1;
120
          mt_mach_bitmask = 1 << MACH_MS1;
121
          mt_arch = ms1_16_002;
122
        }
123
      else if (strcmp (arg, "ms1-16-003") == 0)
124
        {
125
          mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MRISC2;
126
          mt_mach = bfd_mach_mrisc2;
127
          mt_mach_bitmask = 1 << MACH_MS1_003;
128
          mt_arch = ms1_16_003;
129
        }
130
      else if (strcmp (arg, "ms2") == 0)
131
        {
132
          mt_flags = (mt_flags & ~EF_MT_CPU_MASK) | EF_MT_CPU_MS2;
133
          mt_mach = bfd_mach_mrisc2;
134
          mt_mach_bitmask = 1 << MACH_MS2;
135
          mt_arch = ms2;
136
        }
137
    case OPTION_NO_SCHED_REST:
138
      no_scheduling_restrictions = 1;
139
      break;
140
    default:
141
      return 0;
142
    }
143
 
144
  return 1;
145
}
146
 
147
 
148
void
149
md_show_usage (FILE * stream)
150
{
151
  fprintf (stream, _("MT specific command line options:\n"));
152
  fprintf (stream, _("  -march=ms1-64-001         allow ms1-64-001 instructions\n"));
153
  fprintf (stream, _("  -march=ms1-16-002         allow ms1-16-002 instructions (default)\n"));
154
  fprintf (stream, _("  -march=ms1-16-003         allow ms1-16-003 instructions\n"));
155
  fprintf (stream, _("  -march=ms2                allow ms2 instructions \n"));
156
  fprintf (stream, _("  -nosched                  disable scheduling restrictions\n"));
157
}
158
 
159
 
160
void
161
md_begin (void)
162
{
163
  /* Initialize the `cgen' interface.  */
164
 
165
  /* Set the machine number and endian.  */
166
  gas_cgen_cpu_desc = mt_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, mt_mach_bitmask,
167
                                        CGEN_CPU_OPEN_ENDIAN,
168
                                        CGEN_ENDIAN_BIG,
169
                                        CGEN_CPU_OPEN_END);
170
  mt_cgen_init_asm (gas_cgen_cpu_desc);
171
 
172
  /* This is a callback from cgen to gas to parse operands.  */
173
  cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
174
 
175
  /* Set the ELF flags if desired. */
176
  if (mt_flags)
177
    bfd_set_private_flags (stdoutput, mt_flags);
178
 
179
  /* Set the machine type.  */
180
  bfd_default_set_arch_mach (stdoutput, bfd_arch_mt, mt_mach);
181
}
182
 
183
void
184
md_assemble (char * str)
185
{
186
  static long delayed_load_register = 0;
187
  static long prev_delayed_load_register = 0;
188
  static int last_insn_had_delay_slot = 0;
189
  static int last_insn_in_noncond_delay_slot = 0;
190
  static int last_insn_has_load_delay = 0;
191
  static int last_insn_was_memory_access = 0;
192
  static int last_insn_was_io_insn = 0;
193
  static int last_insn_was_arithmetic_or_logic = 0;
194
  static int last_insn_was_branch_insn = 0;
195
  static int last_insn_was_conditional_branch_insn = 0;
196
 
197
  mt_insn insn;
198
  char * errmsg;
199
 
200
  /* Initialize GAS's cgen interface for a new instruction.  */
201
  gas_cgen_init_parse ();
202
 
203
  insn.insn = mt_cgen_assemble_insn
204
      (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
205
 
206
  if (!insn.insn)
207
    {
208
      as_bad ("%s", errmsg);
209
      return;
210
    }
211
 
212
  /* Doesn't really matter what we pass for RELAX_P here.  */
213
  gas_cgen_finish_insn (insn.insn, insn.buffer,
214
                        CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
215
 
216
 
217
  /* Handle Scheduling Restrictions.  */
218
  if (!no_scheduling_restrictions)
219
    {
220
      /* Detect consecutive Memory Accesses.  */
221
      if (last_insn_was_memory_access
222
          && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS)
223
          && mt_mach == ms1_64_001)
224
        as_warn (_("instruction %s may not follow another memory access instruction."),
225
                 CGEN_INSN_NAME (insn.insn));
226
 
227
      /* Detect consecutive I/O Instructions.  */
228
      else if (last_insn_was_io_insn
229
               && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN))
230
        as_warn (_("instruction %s may not follow another I/O instruction."),
231
                 CGEN_INSN_NAME (insn.insn));
232
 
233
      /* Detect consecutive branch instructions.  */
234
      else if (last_insn_was_branch_insn
235
               && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN))
236
        as_warn (_("%s may not occupy the delay slot of another branch insn."),
237
                 CGEN_INSN_NAME (insn.insn));
238
 
239
      /* Detect data dependencies on delayed loads: memory and input insns.  */
240
      if (last_insn_has_load_delay && delayed_load_register)
241
        {
242
          if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
243
              && insn.fields.f_sr1 == delayed_load_register)
244
            as_warn (_("operand references R%ld of previous load."),
245
                     insn.fields.f_sr1);
246
 
247
          if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
248
              && insn.fields.f_sr2 == delayed_load_register)
249
            as_warn (_("operand references R%ld of previous load."),
250
                     insn.fields.f_sr2);
251
        }
252
 
253
      /* Detect JAL/RETI hazard */
254
      if (mt_mach == ms2
255
          && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_JAL_HAZARD))
256
        {
257
          if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
258
               && insn.fields.f_sr1 == delayed_load_register)
259
              || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
260
                  && insn.fields.f_sr2 == delayed_load_register))
261
            as_warn (_("operand references R%ld of previous instrutcion."),
262
                     delayed_load_register);
263
          else if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
264
                    && insn.fields.f_sr1 == prev_delayed_load_register)
265
                   || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
266
                       && insn.fields.f_sr2 == prev_delayed_load_register))
267
            as_warn (_("operand references R%ld of instructcion before previous."),
268
                     prev_delayed_load_register);
269
        }
270
 
271
      /* Detect data dependency between conditional branch instruction
272
         and an immediately preceding arithmetic or logical instruction.  */
273
      if (last_insn_was_arithmetic_or_logic
274
          && !last_insn_in_noncond_delay_slot
275
          && (delayed_load_register != 0)
276
          && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
277
          && mt_arch == ms1_64_001)
278
        {
279
          if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1)
280
              && insn.fields.f_sr1 == delayed_load_register)
281
            as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
282
                     insn.fields.f_sr1);
283
 
284
          if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2)
285
              && insn.fields.f_sr2 == delayed_load_register)
286
            as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."),
287
                     insn.fields.f_sr2);
288
        }
289
    }
290
 
291
  /* Keep track of details of this insn for processing next insn.  */
292
  last_insn_in_noncond_delay_slot = last_insn_was_branch_insn
293
    && !last_insn_was_conditional_branch_insn;
294
 
295
  last_insn_had_delay_slot =
296
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT);
297
 
298
  last_insn_has_load_delay =
299
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY);
300
 
301
  last_insn_was_memory_access =
302
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS);
303
 
304
  last_insn_was_io_insn =
305
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN);
306
 
307
  last_insn_was_arithmetic_or_logic =
308
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_AL_INSN);
309
 
310
  last_insn_was_branch_insn =
311
    CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN);
312
 
313
  last_insn_was_conditional_branch_insn =
314
  CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)
315
    && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2);
316
 
317
  prev_delayed_load_register = delayed_load_register;
318
 
319
  if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDR))
320
     delayed_load_register = insn.fields.f_dr;
321
  else if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDRRR))
322
     delayed_load_register = insn.fields.f_drrr;
323
  else  /* Insns has no destination register.  */
324
     delayed_load_register = 0;
325
 
326
  /* Generate dwarf2 line numbers.  */
327
  dwarf2_emit_insn (4);
328
}
329
 
330
valueT
331
md_section_align (segT segment, valueT size)
332
{
333
  int align = bfd_get_section_alignment (stdoutput, segment);
334
 
335
  return ((size + (1 << align) - 1) & (-1 << align));
336
}
337
 
338
symbolS *
339
md_undefined_symbol (char * name ATTRIBUTE_UNUSED)
340
{
341
    return NULL;
342
}
343
 
344
int
345
md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
346
                               segT    segment ATTRIBUTE_UNUSED)
347
{
348
  as_fatal (_("md_estimate_size_before_relax\n"));
349
  return 1;
350
}
351
 
352
/* *fragP has been relaxed to its final size, and now needs to have
353
   the bytes inside it modified to conform to the new size.
354
 
355
   Called after relaxation is finished.
356
   fragP->fr_type == rs_machine_dependent.
357
   fragP->fr_subtype is the subtype of what the address relaxed to.  */
358
 
359
void
360
md_convert_frag (bfd   * abfd  ATTRIBUTE_UNUSED,
361
                 segT    sec   ATTRIBUTE_UNUSED,
362
                 fragS * fragP ATTRIBUTE_UNUSED)
363
{
364
}
365
 
366
 
367
/* Functions concerning relocs.  */
368
 
369
long
370
md_pcrel_from_section (fixS *fixP, segT sec)
371
{
372
  if (fixP->fx_addsy != (symbolS *) NULL
373
      && (!S_IS_DEFINED (fixP->fx_addsy)
374
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
375
    /* The symbol is undefined (or is defined but not in this section).
376
       Let the linker figure it out.  */
377
    return 0;
378
 
379
  /* Return the address of the opcode - cgen adjusts for opcode size
380
     itself, to be consistent with the disassembler, which must do
381
     so.  */
382
  return fixP->fx_where + fixP->fx_frag->fr_address;
383
}
384
 
385
 
386
/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
387
   Returns BFD_RELOC_NONE if no reloc type can be found.
388
   *FIXP may be modified if desired.  */
389
 
390
bfd_reloc_code_real_type
391
md_cgen_lookup_reloc (const CGEN_INSN *    insn     ATTRIBUTE_UNUSED,
392
                      const CGEN_OPERAND * operand,
393
                      fixS *               fixP     ATTRIBUTE_UNUSED)
394
{
395
  bfd_reloc_code_real_type result;
396
 
397
  result = BFD_RELOC_NONE;
398
 
399
  switch (operand->type)
400
    {
401
    case MT_OPERAND_IMM16O:
402
      result = BFD_RELOC_16_PCREL;
403
      fixP->fx_pcrel = 1;
404
      /* fixP->fx_no_overflow = 1; */
405
      break;
406
    case MT_OPERAND_IMM16:
407
    case MT_OPERAND_IMM16Z:
408
      /* These may have been processed at parse time.  */
409
      if (fixP->fx_cgen.opinfo != 0)
410
        result = fixP->fx_cgen.opinfo;
411
      fixP->fx_no_overflow = 1;
412
      break;
413
    case MT_OPERAND_LOOPSIZE:
414
      result = BFD_RELOC_MT_PCINSN8;
415
      fixP->fx_pcrel = 1;
416
      /* Adjust for the delay slot, which is not part of the loop  */
417
      fixP->fx_offset -= 8;
418
      break;
419
    default:
420
      result = BFD_RELOC_NONE;
421
      break;
422
    }
423
 
424
  return result;
425
}
426
 
427
/* Write a value out to the object file, using the appropriate endianness.  */
428
 
429
void
430
md_number_to_chars (char * buf, valueT val, int n)
431
{
432
  number_to_chars_bigendian (buf, val, n);
433
}
434
 
435
char *
436
md_atof (int type, char * litP, int * sizeP)
437
{
438
  return ieee_md_atof (type, litP, sizeP, FALSE);
439
}
440
 
441
/* See whether we need to force a relocation into the output file.  */
442
 
443
int
444
mt_force_relocation (fixS * fixp ATTRIBUTE_UNUSED)
445
{
446
  return 0;
447
}
448
 
449
void
450
mt_apply_fix (fixS *fixP, valueT *valueP, segT seg)
451
{
452
  if ((fixP->fx_pcrel != 0) && (fixP->fx_r_type == BFD_RELOC_32))
453
    fixP->fx_r_type = BFD_RELOC_32_PCREL;
454
 
455
  gas_cgen_md_apply_fix (fixP, valueP, seg);
456
}
457
 
458
bfd_boolean
459
mt_fix_adjustable (fixS * fixP)
460
{
461
  bfd_reloc_code_real_type reloc_type;
462
 
463
  if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
464
    {
465
      const CGEN_INSN *insn = NULL;
466
      int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
467
      const CGEN_OPERAND *operand;
468
 
469
      operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
470
      reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
471
    }
472
  else
473
    reloc_type = fixP->fx_r_type;
474
 
475
  if (fixP->fx_addsy == NULL)
476
    return TRUE;
477
 
478
  /* Prevent all adjustments to global symbols.  */
479
  if (S_IS_EXTERNAL (fixP->fx_addsy))
480
    return FALSE;
481
 
482
  if (S_IS_WEAK (fixP->fx_addsy))
483
    return FALSE;
484
 
485
  return 1;
486
}

powered by: WebSVN 2.1.0

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