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

Subversion Repositories open8_urisc

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

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

Line No. Rev Author Line
1 16 khays
/* tc-pj.c -- Assemble code for Pico Java
2
   Copyright 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2009, 2010
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 expression"));
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
 
370
  max = min = 0;
371
  switch (fixP->fx_r_type)
372
    {
373
    case BFD_RELOC_VTABLE_INHERIT:
374
    case BFD_RELOC_VTABLE_ENTRY:
375
      fixP->fx_done = 0;
376
      return;
377
 
378
    case BFD_RELOC_PJ_CODE_REL16:
379
      if (val < -0x8000 || val >= 0x7fff)
380
        as_bad_where (fixP->fx_file, fixP->fx_line, _("pcrel too far"));
381
      buf[0] |= (val >> 8) & 0xff;
382
      buf[1] = val & 0xff;
383
      break;
384
 
385
    case BFD_RELOC_PJ_CODE_HI16:
386
      *buf++ = val >> 24;
387
      *buf++ = val >> 16;
388
      fixP->fx_addnumber = val & 0xffff;
389
      break;
390
 
391
    case BFD_RELOC_PJ_CODE_DIR16:
392
    case BFD_RELOC_PJ_CODE_LO16:
393
      *buf++ = val >> 8;
394
      *buf++ = val >> 0;
395
 
396
      max = 0xffff;
397
      min = -0xffff;
398
      break;
399
 
400
    case BFD_RELOC_8:
401
      max = 0xff;
402
      min = -0xff;
403
      *buf++ = val;
404
      break;
405
 
406
    case BFD_RELOC_PJ_CODE_DIR32:
407
      *buf++ = val >> 24;
408
      *buf++ = val >> 16;
409
      *buf++ = val >> 8;
410
      *buf++ = val >> 0;
411
      break;
412
 
413
    case BFD_RELOC_32:
414
      if (target_big_endian)
415
        {
416
          *buf++ = val >> 24;
417
          *buf++ = val >> 16;
418
          *buf++ = val >> 8;
419
          *buf++ = val >> 0;
420
        }
421
      else
422
        {
423
          *buf++ = val >> 0;
424
          *buf++ = val >> 8;
425
          *buf++ = val >> 16;
426
          *buf++ = val >> 24;
427
        }
428
      break;
429
 
430
    case BFD_RELOC_16:
431
      if (target_big_endian)
432
        {
433
          *buf++ = val >> 8;
434
          *buf++ = val >> 0;
435
        }
436
      else
437
        {
438
          *buf++ = val >> 0;
439
          *buf++ = val >> 8;
440
        }
441
      break;
442
 
443
    default:
444
      abort ();
445
    }
446
 
447
  if (max != 0 && (val < min || val > max))
448
    as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
449
 
450
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
451
    fixP->fx_done = 1;
452
}
453
 
454
/* Put number into target byte order.  Always put values in an
455
   executable section into big endian order.  */
456
 
457
void
458
md_number_to_chars (char *ptr, valueT use, int nbytes)
459
{
460
  if (target_big_endian || now_seg->flags & SEC_CODE)
461
    number_to_chars_bigendian (ptr, use, nbytes);
462
  else
463
    number_to_chars_littleendian (ptr, use, nbytes);
464
}
465
 
466
/* Translate internal representation of relocation info to BFD target
467
   format.  */
468
 
469
arelent *
470
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
471
{
472
  arelent *rel;
473
  bfd_reloc_code_real_type r_type;
474
 
475
  rel = xmalloc (sizeof (arelent));
476
  rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
477
  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
478
  rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
479
 
480
  r_type = fixp->fx_r_type;
481
  rel->addend = fixp->fx_addnumber;
482
  rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
483
 
484
  if (rel->howto == NULL)
485
    {
486
      as_bad_where (fixp->fx_file, fixp->fx_line,
487
                    _("Cannot represent relocation type %s"),
488
                    bfd_get_reloc_code_name (r_type));
489
      /* Set howto to a garbage value so that we can keep going.  */
490
      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
491
      gas_assert (rel->howto != NULL);
492
    }
493
 
494
  return rel;
495
}

powered by: WebSVN 2.1.0

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