~ubuntu-branches/ubuntu/utopic/binutils-arm64-cross/utopic

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-06-20 17:38:09 UTC
  • Revision ID: package-import@ubuntu.com-20130620173809-app8lzgvymy5fg6c
Tags: 0.7
Build-depend on binutils-source (>= 2.23.52.20130620-1~).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* tc-moxie.c -- Assemble code for moxie
 
2
   Copyright 2009, 2012
 
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 Anthony Green <green@moxielogic.com>.  */
 
23
 
 
24
#include "as.h"
 
25
#include "safe-ctype.h"
 
26
#include "opcode/moxie.h"
 
27
#include "elf/moxie.h"
 
28
 
 
29
extern const moxie_opc_info_t moxie_opc_info[128];
 
30
 
 
31
const char comment_chars[]        = "#";
 
32
const char line_separator_chars[] = ";";
 
33
const char line_comment_chars[]   = "#";
 
34
 
 
35
static int pending_reloc;
 
36
static struct hash_control *opcode_hash_control;
 
37
 
 
38
const pseudo_typeS md_pseudo_table[] =
 
39
{
 
40
  {0, 0, 0}
 
41
};
 
42
 
 
43
const char FLT_CHARS[] = "rRsSfFdDxXpP";
 
44
const char EXP_CHARS[] = "eE";
 
45
 
 
46
static valueT md_chars_to_number (char * buf, int n);
 
47
 
 
48
/* Byte order.  */
 
49
extern int target_big_endian;
 
50
const char *moxie_target_format = DEFAULT_TARGET_FORMAT;
 
51
 
 
52
void
 
53
md_operand (expressionS *op __attribute__((unused)))
 
54
{
 
55
  /* Empty for now. */
 
56
}
 
57
 
 
58
/* This function is called once, at assembler startup time.  It sets
 
59
   up the hash table with all the opcodes in it, and also initializes
 
60
   some aliases for compatibility with other assemblers.  */
 
61
 
 
62
void
 
63
md_begin (void)
 
64
{
 
65
  int count;
 
66
  const moxie_opc_info_t *opcode;
 
67
  opcode_hash_control = hash_new ();
 
68
 
 
69
  /* Insert names into hash table.  */
 
70
  for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
 
71
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
72
 
 
73
  for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
 
74
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
75
 
 
76
  for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
 
77
    hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
 
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
      moxie_target_format = "elf32-bigmoxie";
 
622
      break;
 
623
    case OPTION_EL: 
 
624
      target_big_endian = 0;
 
625
      moxie_target_format = "elf32-littlemoxie";
 
626
      break;
 
627
    default:        
 
628
      return 0;
 
629
    }
 
630
 
 
631
  return 1;
 
632
}
 
633
 
 
634
void
 
635
md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
 
636
{
 
637
  fprintf (stream, _("\
 
638
  -EB                     assemble for a big endian system (default)\n\
 
639
  -EL                     assemble for a little endian system\n"));
 
640
}
 
641
 
 
642
/* Apply a fixup to the object file.  */
 
643
 
 
644
void
 
645
md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, 
 
646
              valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
 
647
{
 
648
  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
 
649
  long val = *valP;
 
650
  long newval;
 
651
  long max, min;
 
652
 
 
653
  max = min = 0;
 
654
  switch (fixP->fx_r_type)
 
655
    {
 
656
    case BFD_RELOC_32:
 
657
      if (target_big_endian)
 
658
        {
 
659
          buf[0] = val >> 24;
 
660
          buf[1] = val >> 16;
 
661
          buf[2] = val >> 8;
 
662
          buf[3] = val >> 0;
 
663
        }
 
664
      else
 
665
        {
 
666
          buf[3] = val >> 24;
 
667
          buf[2] = val >> 16;
 
668
          buf[1] = val >> 8;
 
669
          buf[0] = val >> 0;
 
670
        }
 
671
      buf += 4;
 
672
      break;
 
673
 
 
674
    case BFD_RELOC_16:
 
675
      if (target_big_endian)
 
676
        {
 
677
          buf[0] = val >> 8;
 
678
          buf[1] = val >> 0;
 
679
        }
 
680
      else
 
681
        {
 
682
          buf[1] = val >> 8;
 
683
          buf[0] = val >> 0;
 
684
        }
 
685
      buf += 2;
 
686
      break;
 
687
 
 
688
    case BFD_RELOC_8:
 
689
      *buf++ = val;
 
690
      break;
 
691
 
 
692
    case BFD_RELOC_MOXIE_10_PCREL:
 
693
      if (!val)
 
694
        break;
 
695
      if (val < -1024 || val > 1022)
 
696
        as_bad_where (fixP->fx_file, fixP->fx_line,
 
697
                      _("pcrel too far BFD_RELOC_MOXIE_10"));
 
698
      /* 11 bit offset even numbered, so we remove right bit.  */
 
699
      val >>= 1;
 
700
      newval = md_chars_to_number (buf, 2);
 
701
      newval |= val & 0x03ff;
 
702
      md_number_to_chars (buf, newval, 2);
 
703
      break;
 
704
 
 
705
    default:
 
706
      abort ();
 
707
    }
 
708
 
 
709
  if (max != 0 && (val < min || val > max))
 
710
    as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
 
711
 
 
712
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
 
713
    fixP->fx_done = 1;
 
714
}
 
715
 
 
716
/* Put number into target byte order.  */
 
717
 
 
718
void
 
719
md_number_to_chars (char * ptr, valueT use, int nbytes)
 
720
{
 
721
  if (target_big_endian)
 
722
    number_to_chars_bigendian (ptr, use, nbytes);
 
723
  else
 
724
    number_to_chars_littleendian (ptr, use, nbytes);
 
725
}
 
726
 
 
727
/* Convert from target byte order to host byte order.  */
 
728
 
 
729
static valueT
 
730
md_chars_to_number (char * buf, int n)
 
731
{
 
732
  valueT result = 0;
 
733
  unsigned char * where = (unsigned char *) buf;
 
734
 
 
735
  if (target_big_endian)
 
736
    {
 
737
      while (n--)
 
738
        {
 
739
          result <<= 8;
 
740
          result |= (*where++ & 255);
 
741
        }
 
742
    }
 
743
  else
 
744
    {
 
745
      while (n--)
 
746
        {
 
747
          result <<= 8;
 
748
          result |= (where[n] & 255);
 
749
        }
 
750
    }
 
751
 
 
752
  return result;
 
753
}
 
754
 
 
755
/* Generate a machine-dependent relocation.  */
 
756
arelent *
 
757
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
 
758
{
 
759
  arelent *relP;
 
760
  bfd_reloc_code_real_type code;
 
761
 
 
762
  switch (fixP->fx_r_type)
 
763
    {
 
764
    case BFD_RELOC_32:
 
765
      code = fixP->fx_r_type;
 
766
      break;
 
767
    case BFD_RELOC_MOXIE_10_PCREL:
 
768
      code = fixP->fx_r_type;
 
769
      break;
 
770
    default:
 
771
      as_bad_where (fixP->fx_file, fixP->fx_line,
 
772
                    _("Semantics error.  This type of operand can not be relocated, it must be an assembly-time constant"));
 
773
      return 0;
 
774
    }
 
775
 
 
776
  relP = xmalloc (sizeof (arelent));
 
777
  gas_assert (relP != 0);
 
778
  relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
 
779
  *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
 
780
  relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
 
781
 
 
782
  relP->addend = fixP->fx_offset;
 
783
 
 
784
  /* This is the standard place for KLUDGEs to work around bugs in
 
785
     bfd_install_relocation (first such note in the documentation
 
786
     appears with binutils-2.8).
 
787
 
 
788
     That function bfd_install_relocation does the wrong thing with
 
789
     putting stuff into the addend of a reloc (it should stay out) for a
 
790
     weak symbol.  The really bad thing is that it adds the
 
791
     "segment-relative offset" of the symbol into the reloc.  In this
 
792
     case, the reloc should instead be relative to the symbol with no
 
793
     other offset than the assembly code shows; and since the symbol is
 
794
     weak, any local definition should be ignored until link time (or
 
795
     thereafter).
 
796
     To wit:  weaksym+42  should be weaksym+42 in the reloc,
 
797
     not weaksym+(offset_from_segment_of_local_weaksym_definition)
 
798
 
 
799
     To "work around" this, we subtract the segment-relative offset of
 
800
     "known" weak symbols.  This evens out the extra offset.
 
801
 
 
802
     That happens for a.out but not for ELF, since for ELF,
 
803
     bfd_install_relocation uses the "special function" field of the
 
804
     howto, and does not execute the code that needs to be undone.  */
 
805
 
 
806
  if (OUTPUT_FLAVOR == bfd_target_aout_flavour
 
807
      && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
 
808
      && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
 
809
    {
 
810
      relP->addend -= S_GET_VALUE (fixP->fx_addsy);
 
811
    }
 
812
 
 
813
  relP->howto = bfd_reloc_type_lookup (stdoutput, code);
 
814
  if (! relP->howto)
 
815
    {
 
816
      const char *name;
 
817
 
 
818
      name = S_GET_NAME (fixP->fx_addsy);
 
819
      if (name == NULL)
 
820
        name = _("<unknown>");
 
821
      as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
 
822
                name, bfd_get_reloc_code_name (code));
 
823
    }
 
824
 
 
825
  return relP;
 
826
}
 
827
 
 
828
/* Decide from what point a pc-relative relocation is relative to,
 
829
   relative to the pc-relative fixup.  Er, relatively speaking.  */
 
830
long
 
831
md_pcrel_from (fixS *fixP)
 
832
{
 
833
  valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
 
834
 
 
835
  switch (fixP->fx_r_type)
 
836
    {
 
837
    case BFD_RELOC_32:
 
838
      return addr + 4;
 
839
    case BFD_RELOC_MOXIE_10_PCREL:
 
840
      /* Offset is from the end of the instruction.  */
 
841
      return addr + 2;
 
842
    default:
 
843
      abort ();
 
844
      return addr;
 
845
    }
 
846
}