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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [gas/] [config/] [tc-pj.c] - Blame information for rev 818

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
/* tc-pj.c -- Assemble code for Pico Java
2
   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2009
3
   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
/* Contributed by Steve Chamberlain of Transmeta <sac@pobox.com>.  */
23
 
24
#include "as.h"
25
#include "safe-ctype.h"
26
#include "opcode/pj.h"
27
 
28
extern const pj_opc_info_t pj_opc_info[512];
29
 
30
const char comment_chars[]        = "!/";
31
const char line_separator_chars[] = ";";
32
const char line_comment_chars[]   = "/!#";
33
 
34
static int pending_reloc;
35
static struct hash_control *opcode_hash_control;
36
 
37
static void
38
little (int ignore ATTRIBUTE_UNUSED)
39
{
40
  target_big_endian = 0;
41
}
42
 
43
static void
44
big (int ignore ATTRIBUTE_UNUSED)
45
{
46
  target_big_endian = 1;
47
}
48
 
49
const pseudo_typeS md_pseudo_table[] =
50
{
51
  {"ml",    little, 0},
52
  {"mb",    big,    0},
53
  {0, 0, 0}
54
};
55
 
56
const char FLT_CHARS[] = "rRsSfFdDxXpP";
57
const char EXP_CHARS[] = "eE";
58
 
59
void
60
md_operand (expressionS *op)
61
{
62
  if (strncmp (input_line_pointer, "%hi16", 5) == 0)
63
    {
64
      if (pending_reloc)
65
        as_bad (_("confusing relocation expressions"));
66
      pending_reloc = BFD_RELOC_PJ_CODE_HI16;
67
      input_line_pointer += 5;
68
      expression (op);
69
    }
70
 
71
  if (strncmp (input_line_pointer, "%lo16", 5) == 0)
72
    {
73
      if (pending_reloc)
74
        as_bad (_("confusing relocation expressions"));
75
      pending_reloc = BFD_RELOC_PJ_CODE_LO16;
76
      input_line_pointer += 5;
77
      expression (op);
78
    }
79
}
80
 
81
/* Parse an expression and then restore the input line pointer.  */
82
 
83
static char *
84
parse_exp_save_ilp (char *s, expressionS *op)
85
{
86
  char *save = input_line_pointer;
87
 
88
  input_line_pointer = s;
89
  expression (op);
90
  s = input_line_pointer;
91
  input_line_pointer = save;
92
  return s;
93
}
94
 
95
/* This is called by emit_expr via TC_CONS_FIX_NEW when creating a
96
   reloc for a cons.  We could use the definition there, except that
97
   we want to handle magic pending reloc expressions specially.  */
98
 
99
void
100
pj_cons_fix_new_pj (fragS *frag, int where, int nbytes, expressionS *exp)
101
{
102
  static int rv[5][2] =
103
  { { 0, 0 },
104
    { BFD_RELOC_8, BFD_RELOC_8 },
105
    { BFD_RELOC_PJ_CODE_DIR16, BFD_RELOC_16 },
106
    { 0, 0 },
107
    { BFD_RELOC_PJ_CODE_DIR32, BFD_RELOC_32 }};
108
 
109
  fix_new_exp (frag, where, nbytes, exp, 0,
110
               pending_reloc ? pending_reloc
111
               : rv[nbytes][(now_seg->flags & SEC_CODE) ? 0 : 1]);
112
 
113
  pending_reloc = 0;
114
}
115
 
116
/* Turn a reloc description character from the pj-opc.h table into
117
   code which BFD can handle.  */
118
 
119
static int
120
c_to_r (int x)
121
{
122
  switch (x)
123
    {
124
    case O_R8:
125
      return BFD_RELOC_8_PCREL;
126
    case O_U8:
127
    case O_8:
128
      return BFD_RELOC_8;
129
    case O_R16:
130
      return BFD_RELOC_PJ_CODE_REL16;
131
    case O_U16:
132
    case O_16:
133
      return BFD_RELOC_PJ_CODE_DIR16;
134
    case O_R32:
135
      return BFD_RELOC_PJ_CODE_REL32;
136
    case O_32:
137
      return BFD_RELOC_PJ_CODE_DIR32;
138
    }
139
  abort ();
140
  return 0;
141
}
142
 
143
/* Handler for the ipush fake opcode,
144
   turns ipush <foo> into sipush lo16<foo>, sethi hi16<foo>.  */
145
 
146
static void
147
ipush_code (pj_opc_info_t *opcode ATTRIBUTE_UNUSED, char *str)
148
{
149
  char *b = frag_more (6);
150
  expressionS arg;
151
 
152
  b[0] = 0x11;
153
  b[3] = 0xed;
154
  parse_exp_save_ilp (str + 1, &arg);
155
  if (pending_reloc)
156
    {
157
      as_bad (_("can't have relocation for ipush"));
158
      pending_reloc = 0;
159
    }
160
 
161
  fix_new_exp (frag_now, b - frag_now->fr_literal + 1, 2,
162
               &arg, 0, BFD_RELOC_PJ_CODE_DIR16);
163
  fix_new_exp (frag_now, b - frag_now->fr_literal + 4, 2,
164
               &arg, 0, BFD_RELOC_PJ_CODE_HI16);
165
}
166
 
167
/* Insert names into the opcode table which are really mini macros,
168
   not opcodes.  The fakeness is indicated with an opcode of -1.  */
169
 
170
static void
171
fake_opcode (const char *name,
172
             void (*func) (struct pj_opc_info_t *, char *))
173
{
174
  pj_opc_info_t * fake = xmalloc (sizeof (pj_opc_info_t));
175
 
176
  fake->opcode = -1;
177
  fake->opcode_next = -1;
178
  fake->u.func = func;
179
  hash_insert (opcode_hash_control, name, (char *) fake);
180
}
181
 
182
/* Enter another entry into the opcode hash table so the same opcode
183
   can have another name.  */
184
 
185
static void
186
alias (const char *new_name, const char *old)
187
{
188
  hash_insert (opcode_hash_control, new_name,
189
               (char *) hash_find (opcode_hash_control, old));
190
}
191
 
192
/* This function is called once, at assembler startup time.  It sets
193
   up the hash table with all the opcodes in it, and also initializes
194
   some aliases for compatibility with other assemblers.  */
195
 
196
void
197
md_begin (void)
198
{
199
  const pj_opc_info_t *opcode;
200
  opcode_hash_control = hash_new ();
201
 
202
  /* Insert names into hash table.  */
203
  for (opcode = pj_opc_info; opcode->u.name; opcode++)
204
    hash_insert (opcode_hash_control, opcode->u.name, (char *) opcode);
205
 
206
  /* Insert the only fake opcode.  */
207
  fake_opcode ("ipush", ipush_code);
208
 
209
  /* Add some aliases for opcode names.  */
210
  alias ("ifeq_s", "ifeq");
211
  alias ("ifne_s", "ifne");
212
  alias ("if_icmpge_s", "if_icmpge");
213
  alias ("if_icmpne_s", "if_icmpne");
214
  alias ("if_icmpeq_s", "if_icmpeq");
215
  alias ("if_icmpgt_s", "if_icmpgt");
216
  alias ("goto_s", "goto");
217
 
218
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
219
}
220
 
221
/* This is the guts of the machine-dependent assembler.  STR points to
222
   a machine dependent instruction.  This function is supposed to emit
223
   the frags/bytes it assembles to.  */
224
 
225
void
226
md_assemble (char *str)
227
{
228
  char *op_start;
229
  char *op_end;
230
 
231
  pj_opc_info_t *opcode;
232
  char *output;
233
  int idx = 0;
234
  char pend;
235
 
236
  int nlen = 0;
237
 
238
  /* Drop leading whitespace.  */
239
  while (*str == ' ')
240
    str++;
241
 
242
  /* Find the op code end.  */
243
  op_start = str;
244
  for (op_end = str;
245
       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
246
       op_end++)
247
    nlen++;
248
 
249
  pend = *op_end;
250
  *op_end = 0;
251
 
252
  if (nlen == 0)
253
    as_bad (_("can't find opcode "));
254
 
255
  opcode = (pj_opc_info_t *) hash_find (opcode_hash_control, op_start);
256
  *op_end = pend;
257
 
258
  if (opcode == NULL)
259
    {
260
      as_bad (_("unknown opcode %s"), op_start);
261
      return;
262
    }
263
 
264
  dwarf2_emit_insn (0);
265
  if (opcode->opcode == -1)
266
    {
267
      /* It's a fake opcode.  Dig out the args and pretend that was
268
         what we were passed.  */
269
      (*opcode->u.func) (opcode, op_end);
270
    }
271
  else
272
    {
273
      int an;
274
 
275
      output = frag_more (opcode->len);
276
      output[idx++] = opcode->opcode;
277
 
278
      if (opcode->opcode_next != -1)
279
        output[idx++] = opcode->opcode_next;
280
 
281
      for (an = 0; opcode->arg[an]; an++)
282
        {
283
          expressionS arg;
284
 
285
          if (*op_end == ',' && an != 0)
286
            op_end++;
287
 
288
          if (*op_end == 0)
289
            as_bad (_("expected expresssion"));
290
 
291
          op_end = parse_exp_save_ilp (op_end, &arg);
292
 
293
          fix_new_exp (frag_now,
294
                       output - frag_now->fr_literal + idx,
295
                       ASIZE (opcode->arg[an]),
296
                       &arg,
297
                       PCREL (opcode->arg[an]),
298
                       pending_reloc ? pending_reloc : c_to_r (opcode->arg[an]));
299
 
300
          idx += ASIZE (opcode->arg[an]);
301
          pending_reloc = 0;
302
        }
303
 
304
      while (ISSPACE (*op_end))
305
        op_end++;
306
 
307
      if (*op_end != 0)
308
        as_warn (_("extra stuff on line ignored"));
309
 
310
    }
311
 
312
  if (pending_reloc)
313
    as_bad (_("Something forgot to clean up\n"));
314
}
315
 
316
char *
317
md_atof (int type, char *litP, int *sizeP)
318
{
319
  return ieee_md_atof (type, litP, sizeP, target_big_endian);
320
}
321
 
322
const char *md_shortopts = "";
323
 
324
struct option md_longopts[] =
325
{
326
#define OPTION_LITTLE (OPTION_MD_BASE)
327
#define OPTION_BIG    (OPTION_LITTLE + 1)
328
 
329
  {"little", no_argument, NULL, OPTION_LITTLE},
330
  {"big", no_argument, NULL, OPTION_BIG},
331
  {NULL, no_argument, NULL, 0}
332
};
333
size_t md_longopts_size = sizeof (md_longopts);
334
 
335
int
336
md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
337
{
338
  switch (c)
339
    {
340
    case OPTION_LITTLE:
341
      little (0);
342
      break;
343
    case OPTION_BIG:
344
      big (0);
345
      break;
346
    default:
347
      return 0;
348
    }
349
  return 1;
350
}
351
 
352
void
353
md_show_usage (FILE *stream)
354
{
355
  fprintf (stream, _("\
356
PJ options:\n\
357
-little                 generate little endian code\n\
358
-big                    generate big endian code\n"));
359
}
360
 
361
/* Apply a fixup to the object file.  */
362
 
363
void
364
md_apply_fix (fixS *fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
365
{
366
  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
367
  long val = *valP;
368
  long max, min;
369
  int shift;
370
 
371
  max = min = 0;
372
  shift = 0;
373
  switch (fixP->fx_r_type)
374
    {
375
    case BFD_RELOC_VTABLE_INHERIT:
376
    case BFD_RELOC_VTABLE_ENTRY:
377
      fixP->fx_done = 0;
378
      return;
379
 
380
    case BFD_RELOC_PJ_CODE_REL16:
381
      if (val < -0x8000 || val >= 0x7fff)
382
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
383
      buf[0] |= (val >> 8) & 0xff;
384
      buf[1] = val & 0xff;
385
      break;
386
 
387
    case BFD_RELOC_PJ_CODE_HI16:
388
      *buf++ = val >> 24;
389
      *buf++ = val >> 16;
390
      fixP->fx_addnumber = val & 0xffff;
391
      break;
392
 
393
    case BFD_RELOC_PJ_CODE_DIR16:
394
    case BFD_RELOC_PJ_CODE_LO16:
395
      *buf++ = val >> 8;
396
      *buf++ = val >> 0;
397
 
398
      max = 0xffff;
399
      min = -0xffff;
400
      break;
401
 
402
    case BFD_RELOC_8:
403
      max = 0xff;
404
      min = -0xff;
405
      *buf++ = val;
406
      break;
407
 
408
    case BFD_RELOC_PJ_CODE_DIR32:
409
      *buf++ = val >> 24;
410
      *buf++ = val >> 16;
411
      *buf++ = val >> 8;
412
      *buf++ = val >> 0;
413
      break;
414
 
415
    case BFD_RELOC_32:
416
      if (target_big_endian)
417
        {
418
          *buf++ = val >> 24;
419
          *buf++ = val >> 16;
420
          *buf++ = val >> 8;
421
          *buf++ = val >> 0;
422
        }
423
      else
424
        {
425
          *buf++ = val >> 0;
426
          *buf++ = val >> 8;
427
          *buf++ = val >> 16;
428
          *buf++ = val >> 24;
429
        }
430
      break;
431
 
432
    case BFD_RELOC_16:
433
      if (target_big_endian)
434
        {
435
          *buf++ = val >> 8;
436
          *buf++ = val >> 0;
437
        }
438
      else
439
        {
440
          *buf++ = val >> 0;
441
          *buf++ = val >> 8;
442
        }
443
      break;
444
 
445
    default:
446
      abort ();
447
    }
448
 
449
  if (max != 0 && (val < min || val > max))
450
    as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
451
 
452
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
453
    fixP->fx_done = 1;
454
}
455
 
456
/* Put number into target byte order.  Always put values in an
457
   executable section into big endian order.  */
458
 
459
void
460
md_number_to_chars (char *ptr, valueT use, int nbytes)
461
{
462
  if (target_big_endian || now_seg->flags & SEC_CODE)
463
    number_to_chars_bigendian (ptr, use, nbytes);
464
  else
465
    number_to_chars_littleendian (ptr, use, nbytes);
466
}
467
 
468
/* Translate internal representation of relocation info to BFD target
469
   format.  */
470
 
471
arelent *
472
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
473
{
474
  arelent *rel;
475
  bfd_reloc_code_real_type r_type;
476
 
477
  rel = xmalloc (sizeof (arelent));
478
  rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
479
  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
480
  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
481
 
482
  r_type = fixp->fx_r_type;
483
  rel->addend = fixp->fx_addnumber;
484
  rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
485
 
486
  if (rel->howto == NULL)
487
    {
488
      as_bad_where (fixp->fx_file, fixp->fx_line,
489
                    _("Cannot represent relocation type %s"),
490
                    bfd_get_reloc_code_name (r_type));
491
      /* Set howto to a garbage value so that we can keep going.  */
492
      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
493
      gas_assert (rel->howto != NULL);
494
    }
495
 
496
  return rel;
497
}

powered by: WebSVN 2.1.0

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