~angelsl/ubuntu/wily/binutils/mips-cross

« back to all changes in this revision

Viewing changes to gas/config/tc-moxie.c

  • Committer: angelsl
  • Date: 2015-11-03 15:54:40 UTC
  • Revision ID: angelsl-20151103155440-gbh6qo1olzlvaiqs
Import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* tc-moxie.c -- Assemble code for moxie
 
2
   Copyright (C) 2009-2014 Free Software Foundation, Inc.
 
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, 51 Franklin Street - Fifth Floor,
 
19
   Boston, MA 02110-1301, USA.  */
 
20
 
 
21
/* Contributed by Anthony Green <green@moxielogic.com>.  */
 
22
 
 
23
#include "as.h"
 
24
#include "safe-ctype.h"
 
25
#include "opcode/moxie.h"
 
26
#include "elf/moxie.h"
 
27
 
 
28
extern const moxie_opc_info_t moxie_opc_info[128];
 
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
const pseudo_typeS md_pseudo_table[] =
 
38
{
 
39
  {0, 0, 0}
 
40
};
 
41
 
 
42
const char FLT_CHARS[] = "rRsSfFdDxXpP";
 
43
const char EXP_CHARS[] = "eE";
 
44
 
 
45
static valueT md_chars_to_number (char * buf, int n);
 
46
 
 
47
/* Byte order.  */
 
48
extern int target_big_endian;
 
49
 
 
50
void
 
51
md_operand (expressionS *op __attribute__((unused)))
 
52
{
 
53
  /* Empty for now. */
 
54
}
 
55
 
 
56
/* This function is called once, at assembler startup time.  It sets
 
57
   up the hash table with all the opcodes in it, and also initializes
 
58
   some aliases for compatibility with other assemblers.  */
 
59
 
 
60
void
 
61
md_begin (void)
 
62
{
 
63
  int count;
 
64
  const moxie_opc_info_t *opcode;
 
65
  opcode_hash_control = hash_new ();
 
66
 
 
67
  /* Insert names into hash table.  */
 
68
  for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
 
69
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
70
 
 
71
  for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
 
72
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
73
 
 
74
  for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
 
75
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
76
 
 
77
  target_big_endian = TARGET_BYTES_BIG_ENDIAN;
 
78
 
 
79
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
 
80
}
 
81
 
 
82
/* Parse an expression and then restore the input line pointer.  */
 
83
 
 
84
static char *
 
85
parse_exp_save_ilp (char *s, expressionS *op)
 
86
{
 
87
  char *save = input_line_pointer;
 
88
 
 
89
  input_line_pointer = s;
 
90
  expression (op);
 
91
  s = input_line_pointer;
 
92
  input_line_pointer = save;
 
93
  return s;
 
94
}
 
95
 
 
96
static int
 
97
parse_register_operand (char **ptr)
 
98
{
 
99
  int reg;
 
100
  char *s = *ptr;
 
101
 
 
102
  if (*s != '$')
 
103
    {
 
104
      as_bad (_("expecting register"));
 
105
      ignore_rest_of_line ();
 
106
      return -1;
 
107
    }
 
108
  if (s[1] == 'f' && s[2] == 'p')
 
109
    {
 
110
      *ptr += 3;
 
111
      return 0;
 
112
    }
 
113
  if (s[1] == 's' && s[2] == 'p')
 
114
    {
 
115
      *ptr += 3;
 
116
      return 1;
 
117
    }
 
118
  if (s[1] == 'r')
 
119
    {
 
120
      reg = s[2] - '0';
 
121
      if ((reg < 0) || (reg > 9))
 
122
        {
 
123
          as_bad (_("illegal register number"));
 
124
          ignore_rest_of_line ();
 
125
          return -1;
 
126
        }
 
127
      if (reg == 1)
 
128
        {
 
129
          int r2 = s[3] - '0';
 
130
          if ((r2 >= 0) && (r2 <= 3))
 
131
            {
 
132
              reg = 10 + r2;
 
133
              *ptr += 1;
 
134
            }
 
135
        }
 
136
    }
 
137
  else
 
138
    {
 
139
      as_bad (_("illegal register number"));
 
140
      ignore_rest_of_line ();
 
141
      return -1;
 
142
    }
 
143
 
 
144
  *ptr += 3;
 
145
 
 
146
  return reg + 2;
 
147
}
 
148
 
 
149
/* This is the guts of the machine-dependent assembler.  STR points to
 
150
   a machine dependent instruction.  This function is supposed to emit
 
151
   the frags/bytes it assembles to.  */
 
152
 
 
153
void
 
154
md_assemble (char *str)
 
155
{
 
156
  char *op_start;
 
157
  char *op_end;
 
158
 
 
159
  moxie_opc_info_t *opcode;
 
160
  char *p;
 
161
  char pend;
 
162
 
 
163
  unsigned short iword = 0;
 
164
 
 
165
  int nlen = 0;
 
166
 
 
167
  /* Drop leading whitespace.  */
 
168
  while (*str == ' ')
 
169
    str++;
 
170
 
 
171
  /* Find the op code end.  */
 
172
  op_start = str;
 
173
  for (op_end = str;
 
174
       *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
 
175
       op_end++)
 
176
    nlen++;
 
177
 
 
178
  pend = *op_end;
 
179
  *op_end = 0;
 
180
 
 
181
  if (nlen == 0)
 
182
    as_bad (_("can't find opcode "));
 
183
  opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start);
 
184
  *op_end = pend;
 
185
 
 
186
  if (opcode == NULL)
 
187
    {
 
188
      as_bad (_("unknown opcode %s"), op_start);
 
189
      return;
 
190
    }
 
191
 
 
192
  p = frag_more (2);
 
193
 
 
194
  switch (opcode->itype)
 
195
    {
 
196
    case MOXIE_F2_A8V:
 
197
      iword = (1<<15) | (opcode->opcode << 12);
 
198
      while (ISSPACE (*op_end))
 
199
        op_end++;
 
200
      {
 
201
        expressionS arg;
 
202
        int reg;
 
203
        reg = parse_register_operand (&op_end);
 
204
        iword += (reg << 8);
 
205
        if (*op_end != ',')
 
206
          as_warn (_("expecting comma delimited register operands"));
 
207
        op_end++;
 
208
        op_end = parse_exp_save_ilp (op_end, &arg);
 
209
        fix_new_exp (frag_now,
 
210
                     ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
 
211
                     1,
 
212
                     &arg,
 
213
                     0,
 
214
                     BFD_RELOC_8);
 
215
      }
 
216
      break;
 
217
    case MOXIE_F1_AB:
 
218
      iword = opcode->opcode << 8;
 
219
      while (ISSPACE (*op_end))
 
220
        op_end++;
 
221
      {
 
222
        int dest, src;
 
223
        dest = parse_register_operand (&op_end);
 
224
        if (*op_end != ',')
 
225
          as_warn (_("expecting comma delimited register operands"));
 
226
        op_end++;
 
227
        src  = parse_register_operand (&op_end);
 
228
        iword += (dest << 4) + src;
 
229
        while (ISSPACE (*op_end))
 
230
          op_end++;
 
231
        if (*op_end != 0)
 
232
          as_warn (_("extra stuff on line ignored"));
 
233
      }
 
234
      break;
 
235
    case MOXIE_F1_A4:
 
236
      iword = opcode->opcode << 8;
 
237
      while (ISSPACE (*op_end))
 
238
        op_end++;
 
239
      {
 
240
        expressionS arg;
 
241
        char *where;
 
242
        int regnum;
 
243
 
 
244
        regnum = parse_register_operand (&op_end);
 
245
        while (ISSPACE (*op_end))
 
246
          op_end++;
 
247
 
 
248
        iword += (regnum << 4);
 
249
 
 
250
        if (*op_end != ',')
 
251
          {
 
252
            as_bad (_("expecting comma delimited operands"));
 
253
            ignore_rest_of_line ();
 
254
            return;
 
255
          }
 
256
        op_end++;
 
257
 
 
258
        op_end = parse_exp_save_ilp (op_end, &arg);
 
259
        where = frag_more (4);
 
260
        fix_new_exp (frag_now,
 
261
                     (where - frag_now->fr_literal),
 
262
                     4,
 
263
                     &arg,
 
264
                     0,
 
265
                     BFD_RELOC_32);
 
266
      }
 
267
      break;
 
268
    case MOXIE_F1_M:
 
269
    case MOXIE_F1_4:
 
270
      iword = opcode->opcode << 8;
 
271
      while (ISSPACE (*op_end))
 
272
        op_end++;
 
273
      {
 
274
        expressionS arg;
 
275
        char *where;
 
276
 
 
277
        op_end = parse_exp_save_ilp (op_end, &arg);
 
278
        where = frag_more (4);
 
279
        fix_new_exp (frag_now,
 
280
                     (where - frag_now->fr_literal),
 
281
                     4,
 
282
                     &arg,
 
283
                     0,
 
284
                     BFD_RELOC_32);
 
285
      }
 
286
      break;
 
287
    case MOXIE_F1_NARG:
 
288
      iword = opcode->opcode << 8;
 
289
      while (ISSPACE (*op_end))
 
290
        op_end++;
 
291
      if (*op_end != 0)
 
292
        as_warn (_("extra stuff on line ignored"));
 
293
      break;
 
294
    case MOXIE_F1_A:
 
295
      iword = opcode->opcode << 8;
 
296
      while (ISSPACE (*op_end))
 
297
        op_end++;
 
298
      {
 
299
        int reg;
 
300
        reg = parse_register_operand (&op_end);
 
301
        while (ISSPACE (*op_end))
 
302
          op_end++;
 
303
        if (*op_end != 0)
 
304
          as_warn (_("extra stuff on line ignored"));
 
305
        iword += (reg << 4);
 
306
      }
 
307
      break;
 
308
    case MOXIE_F1_ABi:
 
309
      iword = opcode->opcode << 8;
 
310
      while (ISSPACE (*op_end))
 
311
        op_end++;
 
312
      {
 
313
        int a, b;
 
314
        a = parse_register_operand (&op_end);
 
315
        if (*op_end != ',')
 
316
          as_warn (_("expecting comma delimited register operands"));
 
317
        op_end++;
 
318
        if (*op_end != '(')
 
319
          {
 
320
            as_bad (_("expecting indirect register `($rA)'"));
 
321
            ignore_rest_of_line ();
 
322
            return;
 
323
          }
 
324
        op_end++;
 
325
        b = parse_register_operand (&op_end);
 
326
        if (*op_end != ')')
 
327
          {
 
328
            as_bad (_("missing closing parenthesis"));
 
329
            ignore_rest_of_line ();
 
330
            return;
 
331
          }
 
332
        op_end++;
 
333
        iword += (a << 4) + b;
 
334
        while (ISSPACE (*op_end))
 
335
          op_end++;
 
336
        if (*op_end != 0)
 
337
          as_warn (_("extra stuff on line ignored"));
 
338
      }
 
339
      break;
 
340
    case MOXIE_F1_AiB:
 
341
      iword = opcode->opcode << 8;
 
342
      while (ISSPACE (*op_end))
 
343
        op_end++;
 
344
      {
 
345
        int a, b;
 
346
        if (*op_end != '(')
 
347
          {
 
348
            as_bad (_("expecting indirect register `($rA)'"));
 
349
            ignore_rest_of_line ();
 
350
            return;
 
351
          }
 
352
        op_end++;
 
353
        a = parse_register_operand (&op_end);
 
354
        if (*op_end != ')')
 
355
          {
 
356
            as_bad (_("missing closing parenthesis"));
 
357
            ignore_rest_of_line ();
 
358
            return;
 
359
          }
 
360
        op_end++;
 
361
        if (*op_end != ',')
 
362
          as_warn (_("expecting comma delimited register operands"));
 
363
        op_end++;
 
364
        b = parse_register_operand (&op_end);
 
365
        iword += (a << 4) + b;
 
366
        while (ISSPACE (*op_end))
 
367
          op_end++;
 
368
        if (*op_end != 0)
 
369
          as_warn (_("extra stuff on line ignored"));
 
370
      }
 
371
      break;
 
372
    case MOXIE_F1_4A:
 
373
      iword = opcode->opcode << 8;
 
374
      while (ISSPACE (*op_end))
 
375
        op_end++;
 
376
      {
 
377
        expressionS arg;
 
378
        char *where;
 
379
        int a;
 
380
 
 
381
        op_end = parse_exp_save_ilp (op_end, &arg);
 
382
        where = frag_more (4);
 
383
        fix_new_exp (frag_now,
 
384
                     (where - frag_now->fr_literal),
 
385
                     4,
 
386
                     &arg,
 
387
                     0,
 
388
                     BFD_RELOC_32);
 
389
 
 
390
        if (*op_end != ',')
 
391
          {
 
392
            as_bad (_("expecting comma delimited operands"));
 
393
            ignore_rest_of_line ();
 
394
            return;
 
395
          }
 
396
        op_end++;
 
397
 
 
398
        a = parse_register_operand (&op_end);
 
399
        while (ISSPACE (*op_end))
 
400
          op_end++;
 
401
        if (*op_end != 0)
 
402
          as_warn (_("extra stuff on line ignored"));
 
403
 
 
404
        iword += (a << 4);
 
405
      }
 
406
      break;
 
407
    case MOXIE_F1_ABi4:
 
408
      iword = opcode->opcode << 8;
 
409
      while (ISSPACE (*op_end))
 
410
        op_end++;
 
411
      {
 
412
        expressionS arg;
 
413
        char *offset;
 
414
        int a, b;
 
415
 
 
416
        a = parse_register_operand (&op_end);
 
417
        while (ISSPACE (*op_end))
 
418
          op_end++;
 
419
 
 
420
        if (*op_end != ',')
 
421
          {
 
422
            as_bad (_("expecting comma delimited operands"));
 
423
            ignore_rest_of_line ();
 
424
            return;
 
425
          }
 
426
        op_end++;
 
427
 
 
428
        op_end = parse_exp_save_ilp (op_end, &arg);
 
429
        offset = frag_more (4);
 
430
        fix_new_exp (frag_now,
 
431
                     (offset - frag_now->fr_literal),
 
432
                     4,
 
433
                     &arg,
 
434
                     0,
 
435
                     BFD_RELOC_32);
 
436
 
 
437
        if (*op_end != '(')
 
438
          {
 
439
            as_bad (_("expecting indirect register `($rX)'"));
 
440
            ignore_rest_of_line ();
 
441
            return;
 
442
          }
 
443
        op_end++;
 
444
        b = parse_register_operand (&op_end);
 
445
        if (*op_end != ')')
 
446
          {
 
447
            as_bad (_("missing closing parenthesis"));
 
448
            ignore_rest_of_line ();
 
449
            return;
 
450
          }
 
451
        op_end++;
 
452
 
 
453
        while (ISSPACE (*op_end))
 
454
          op_end++;
 
455
        if (*op_end != 0)
 
456
          as_warn (_("extra stuff on line ignored"));
 
457
 
 
458
        iword += (a << 4) + b;
 
459
      }
 
460
      break;
 
461
    case MOXIE_F1_AiB4:
 
462
      iword = opcode->opcode << 8;
 
463
      while (ISSPACE (*op_end))
 
464
        op_end++;
 
465
      {
 
466
        expressionS arg;
 
467
        char *offset;
 
468
        int a, b;
 
469
 
 
470
        op_end = parse_exp_save_ilp (op_end, &arg);
 
471
        offset = frag_more (4);
 
472
        fix_new_exp (frag_now,
 
473
                     (offset - frag_now->fr_literal),
 
474
                     4,
 
475
                     &arg,
 
476
                     0,
 
477
                     BFD_RELOC_32);
 
478
 
 
479
        if (*op_end != '(')
 
480
          {
 
481
            as_bad (_("expecting indirect register `($rX)'"));
 
482
            ignore_rest_of_line ();
 
483
            return;
 
484
          }
 
485
        op_end++;
 
486
        a = parse_register_operand (&op_end);
 
487
        if (*op_end != ')')
 
488
          {
 
489
            as_bad (_("missing closing parenthesis"));
 
490
            ignore_rest_of_line ();
 
491
            return;
 
492
          }
 
493
        op_end++;
 
494
 
 
495
        if (*op_end != ',')
 
496
          {
 
497
            as_bad (_("expecting comma delimited operands"));
 
498
            ignore_rest_of_line ();
 
499
            return;
 
500
          }
 
501
        op_end++;
 
502
 
 
503
        b = parse_register_operand (&op_end);
 
504
        while (ISSPACE (*op_end))
 
505
          op_end++;
 
506
 
 
507
        while (ISSPACE (*op_end))
 
508
          op_end++;
 
509
        if (*op_end != 0)
 
510
          as_warn (_("extra stuff on line ignored"));
 
511
 
 
512
        iword += (a << 4) + b;
 
513
      }
 
514
      break;
 
515
    case MOXIE_F2_NARG:
 
516
      iword = opcode->opcode << 12;
 
517
      while (ISSPACE (*op_end))
 
518
        op_end++;
 
519
      if (*op_end != 0)
 
520
        as_warn (_("extra stuff on line ignored"));
 
521
      break;
 
522
    case MOXIE_F3_PCREL:
 
523
      iword = (3<<14) | (opcode->opcode << 10);
 
524
      while (ISSPACE (*op_end))
 
525
        op_end++;
 
526
      {
 
527
        expressionS arg;
 
528
 
 
529
        op_end = parse_exp_save_ilp (op_end, &arg);
 
530
        fix_new_exp (frag_now,
 
531
                     (p - frag_now->fr_literal),
 
532
                     2,
 
533
                     &arg,
 
534
                     TRUE,
 
535
                     BFD_RELOC_MOXIE_10_PCREL);
 
536
      }
 
537
      break;
 
538
    default:
 
539
      abort ();
 
540
    }
 
541
 
 
542
  md_number_to_chars (p, iword, 2);
 
543
 
 
544
  while (ISSPACE (*op_end))
 
545
    op_end++;
 
546
 
 
547
  if (*op_end != 0)
 
548
    as_warn (_("extra stuff on line ignored"));
 
549
 
 
550
  if (pending_reloc)
 
551
    as_bad (_("Something forgot to clean up\n"));
 
552
}
 
553
 
 
554
/* Turn a string in input_line_pointer into a floating point constant
 
555
   of type type, and store the appropriate bytes in *LITP.  The number
 
556
   of LITTLENUMS emitted is stored in *SIZEP .  An error message is
 
557
   returned, or NULL on OK.  */
 
558
 
 
559
char *
 
560
md_atof (int type, char *litP, int *sizeP)
 
561
{
 
562
  int prec;
 
563
  LITTLENUM_TYPE words[4];
 
564
  char *t;
 
565
  int i;
 
566
 
 
567
  switch (type)
 
568
    {
 
569
    case 'f':
 
570
      prec = 2;
 
571
      break;
 
572
 
 
573
    case 'd':
 
574
      prec = 4;
 
575
      break;
 
576
 
 
577
    default:
 
578
      *sizeP = 0;
 
579
      return _("bad call to md_atof");
 
580
    }
 
581
 
 
582
  t = atof_ieee (input_line_pointer, type, words);
 
583
  if (t)
 
584
    input_line_pointer = t;
 
585
 
 
586
  *sizeP = prec * 2;
 
587
 
 
588
  for (i = prec - 1; i >= 0; i--)
 
589
    {
 
590
      md_number_to_chars (litP, (valueT) words[i], 2);
 
591
      litP += 2;
 
592
    }
 
593
 
 
594
  return NULL;
 
595
}
 
596
 
 
597
enum options
 
598
{
 
599
  OPTION_EB = OPTION_MD_BASE,
 
600
  OPTION_EL,
 
601
};
 
602
 
 
603
struct option md_longopts[] =
 
604
{
 
605
  { "EB",          no_argument, NULL, OPTION_EB},
 
606
  { "EL",          no_argument, NULL, OPTION_EL},
 
607
  { NULL,          no_argument, NULL, 0}
 
608
};
 
609
 
 
610
size_t md_longopts_size = sizeof (md_longopts);
 
611
 
 
612
const char *md_shortopts = "";
 
613
 
 
614
int
 
615
md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
 
616
{
 
617
  switch (c)
 
618
    {
 
619
    case OPTION_EB: 
 
620
      target_big_endian = 1; 
 
621
      break;
 
622
    case OPTION_EL: 
 
623
      target_big_endian = 0;
 
624
      break;
 
625
    default:        
 
626
      return 0;
 
627
    }
 
628
 
 
629
  return 1;
 
630
}
 
631
 
 
632
void
 
633
md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
 
634
{
 
635
  fprintf (stream, _("\
 
636
  -EB                     assemble for a big endian system (default)\n\
 
637
  -EL                     assemble for a little endian system\n"));
 
638
}
 
639
 
 
640
/* Apply a fixup to the object file.  */
 
641
 
 
642
void
 
643
md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, 
 
644
              valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
 
645
{
 
646
  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 
647
  long val = *valP;
 
648
  long newval;
 
649
  long max, min;
 
650
 
 
651
  max = min = 0;
 
652
  switch (fixP->fx_r_type)
 
653
    {
 
654
    case BFD_RELOC_32:
 
655
      if (target_big_endian)
 
656
        {
 
657
          buf[0] = val >> 24;
 
658
          buf[1] = val >> 16;
 
659
          buf[2] = val >> 8;
 
660
          buf[3] = val >> 0;
 
661
        }
 
662
      else
 
663
        {
 
664
          buf[3] = val >> 24;
 
665
          buf[2] = val >> 16;
 
666
          buf[1] = val >> 8;
 
667
          buf[0] = val >> 0;
 
668
        }
 
669
      buf += 4;
 
670
      break;
 
671
 
 
672
    case BFD_RELOC_16:
 
673
      if (target_big_endian)
 
674
        {
 
675
          buf[0] = val >> 8;
 
676
          buf[1] = val >> 0;
 
677
        }
 
678
      else
 
679
        {
 
680
          buf[1] = val >> 8;
 
681
          buf[0] = val >> 0;
 
682
        }
 
683
      buf += 2;
 
684
      break;
 
685
 
 
686
    case BFD_RELOC_8:
 
687
      *buf++ = val;
 
688
      break;
 
689
 
 
690
    case BFD_RELOC_MOXIE_10_PCREL:
 
691
      if (!val)
 
692
        break;
 
693
      if (val < -1024 || val > 1022)
 
694
        as_bad_where (fixP->fx_file, fixP->fx_line,
 
695
                      _("pcrel too far BFD_RELOC_MOXIE_10"));
 
696
      /* 11 bit offset even numbered, so we remove right bit.  */
 
697
      val >>= 1;
 
698
      newval = md_chars_to_number (buf, 2);
 
699
      newval |= val & 0x03ff;
 
700
      md_number_to_chars (buf, newval, 2);
 
701
      break;
 
702
 
 
703
    default:
 
704
      abort ();
 
705
    }
 
706
 
 
707
  if (max != 0 && (val < min || val > max))
 
708
    as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
 
709
 
 
710
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
 
711
    fixP->fx_done = 1;
 
712
}
 
713
 
 
714
/* Put number into target byte order.  */
 
715
 
 
716
void
 
717
md_number_to_chars (char * ptr, valueT use, int nbytes)
 
718
{
 
719
  if (target_big_endian)
 
720
    number_to_chars_bigendian (ptr, use, nbytes);
 
721
  else
 
722
    number_to_chars_littleendian (ptr, use, nbytes);
 
723
}
 
724
 
 
725
/* Convert from target byte order to host byte order.  */
 
726
 
 
727
static valueT
 
728
md_chars_to_number (char * buf, int n)
 
729
{
 
730
  valueT result = 0;
 
731
  unsigned char * where = (unsigned char *) buf;
 
732
 
 
733
  if (target_big_endian)
 
734
    {
 
735
      while (n--)
 
736
        {
 
737
          result <<= 8;
 
738
          result |= (*where++ & 255);
 
739
        }
 
740
    }
 
741
  else
 
742
    {
 
743
      while (n--)
 
744
        {
 
745
          result <<= 8;
 
746
          result |= (where[n] & 255);
 
747
        }
 
748
    }
 
749
 
 
750
  return result;
 
751
}
 
752
 
 
753
/* Generate a machine-dependent relocation.  */
 
754
arelent *
 
755
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
 
756
{
 
757
  arelent *relP;
 
758
  bfd_reloc_code_real_type code;
 
759
 
 
760
  switch (fixP->fx_r_type)
 
761
    {
 
762
    case BFD_RELOC_32:
 
763
      code = fixP->fx_r_type;
 
764
      break;
 
765
    case BFD_RELOC_MOXIE_10_PCREL:
 
766
      code = fixP->fx_r_type;
 
767
      break;
 
768
    default:
 
769
      as_bad_where (fixP->fx_file, fixP->fx_line,
 
770
                    _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
 
771
      return 0;
 
772
    }
 
773
 
 
774
  relP = xmalloc (sizeof (arelent));
 
775
  gas_assert (relP != 0);
 
776
  relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
 
777
  *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
 
778
  relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
 
779
 
 
780
  relP->addend = fixP->fx_offset;
 
781
 
 
782
  /* This is the standard place for KLUDGEs to work around bugs in
 
783
     bfd_install_relocation (first such note in the documentation
 
784
     appears with binutils-2.8).
 
785
 
 
786
     That function bfd_install_relocation does the wrong thing with
 
787
     putting stuff into the addend of a reloc (it should stay out) for a
 
788
     weak symbol.  The really bad thing is that it adds the
 
789
     "segment-relative offset" of the symbol into the reloc.  In this
 
790
     case, the reloc should instead be relative to the symbol with no
 
791
     other offset than the assembly code shows; and since the symbol is
 
792
     weak, any local definition should be ignored until link time (or
 
793
     thereafter).
 
794
     To wit:  weaksym+42  should be weaksym+42 in the reloc,
 
795
     not weaksym+(offset_from_segment_of_local_weaksym_definition)
 
796
 
 
797
     To "work around" this, we subtract the segment-relative offset of
 
798
     "known" weak symbols.  This evens out the extra offset.
 
799
 
 
800
     That happens for a.out but not for ELF, since for ELF,
 
801
     bfd_install_relocation uses the "special function" field of the
 
802
     howto, and does not execute the code that needs to be undone.  */
 
803
 
 
804
  if (OUTPUT_FLAVOR == bfd_target_aout_flavour
 
805
      && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
 
806
      && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
 
807
    {
 
808
      relP->addend -= S_GET_VALUE (fixP->fx_addsy);
 
809
    }
 
810
 
 
811
  relP->howto = bfd_reloc_type_lookup (stdoutput, code);
 
812
  if (! relP->howto)
 
813
    {
 
814
      const char *name;
 
815
 
 
816
      name = S_GET_NAME (fixP->fx_addsy);
 
817
      if (name == NULL)
 
818
        name = _("<unknown>");
 
819
      as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
 
820
                name, bfd_get_reloc_code_name (code));
 
821
    }
 
822
 
 
823
  return relP;
 
824
}
 
825
 
 
826
/* Decide from what point a pc-relative relocation is relative to,
 
827
   relative to the pc-relative fixup.  Er, relatively speaking.  */
 
828
long
 
829
md_pcrel_from (fixS *fixP)
 
830
{
 
831
  valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 
832
 
 
833
  switch (fixP->fx_r_type)
 
834
    {
 
835
    case BFD_RELOC_32:
 
836
      return addr + 4;
 
837
    case BFD_RELOC_MOXIE_10_PCREL:
 
838
      /* Offset is from the end of the instruction.  */
 
839
      return addr + 2;
 
840
    default:
 
841
      abort ();
 
842
      return addr;
 
843
    }
 
844
}