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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-tic4x.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-tic4x.c -- Assemble for the Texas Instruments TMS320C[34]x.
2
   Copyright (C) 1997,1998, 2002, 2003, 2005, 2006, 2007, 2008
3
   Free Software Foundation. Inc.
4
 
5
   Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
6
 
7
   This file is part of GAS, the GNU Assembler.
8
 
9
   GAS is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3, or (at your option)
12
   any later version.
13
 
14
   GAS is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with GAS; see the file COPYING.  If not, write to
21
   the Free Software Foundation, 51 Franklin Street - Fifth Floor,
22
   Boston, MA 02110-1301, USA.  */
23
/*
24
  TODOs:
25
  ------
26
 
27
  o .align cannot handle fill-data-width larger than 0xFF/8-bits. It
28
    should be possible to define a 32-bits pattern.
29
 
30
  o .align fills all section with NOP's when used regardless if has
31
    been used in .text or .data. (However the .align is primarily
32
    intended used in .text sections. If you require something else,
33
    use .align <size>,0x00)
34
 
35
  o .align: Implement a 'bu' insn if the number of nop's exceeds 4
36
    within the align frag. if(fragsize>4words) insert bu fragend+1
37
    first.
38
 
39
  o .usect if has symbol on previous line not implemented
40
 
41
  o .sym, .eos, .stag, .etag, .member not implemented
42
 
43
  o Evaluation of constant floating point expressions (expr.c needs
44
    work!)
45
 
46
  o Support 'abc' constants (that is 0x616263)
47
*/
48
 
49
#include "safe-ctype.h"
50
#include "as.h"
51
#include "opcode/tic4x.h"
52
#include "subsegs.h"
53
#include "obstack.h"
54
 
55
/* OK, we accept a syntax similar to the other well known C30
56
   assembly tools.  With TIC4X_ALT_SYNTAX defined we are more
57
   flexible, allowing a more Unix-like syntax:  `%' in front of
58
   register names, `#' in front of immediate constants, and
59
   not requiring `@' in front of direct addresses.  */
60
 
61
#define TIC4X_ALT_SYNTAX
62
 
63
/* Equal to MAX_PRECISION in atof-ieee.c.  */
64
#define MAX_LITTLENUMS 6        /* (12 bytes) */
65
 
66
/* Handle of the inst mnemonic hash table.  */
67
static struct hash_control *tic4x_op_hash = NULL;
68
 
69
/* Handle asg pseudo.  */
70
static struct hash_control *tic4x_asg_hash = NULL;
71
 
72
static unsigned int tic4x_cpu = 0;        /* Default to TMS320C40.  */
73
static unsigned int tic4x_revision = 0;   /* CPU revision */
74
static unsigned int tic4x_idle2 = 0;      /* Idle2 support */
75
static unsigned int tic4x_lowpower = 0;   /* Lowpower support */
76
static unsigned int tic4x_enhanced = 0;   /* Enhanced opcode support */
77
static unsigned int tic4x_big_model = 0;  /* Default to small memory model.  */
78
static unsigned int tic4x_reg_args = 0;   /* Default to args passed on stack.  */
79
static unsigned long tic4x_oplevel = 0;   /* Opcode level */
80
 
81
#define OPTION_CPU      'm'
82
#define OPTION_BIG      (OPTION_MD_BASE + 1)
83
#define OPTION_SMALL    (OPTION_MD_BASE + 2)
84
#define OPTION_MEMPARM  (OPTION_MD_BASE + 3)
85
#define OPTION_REGPARM  (OPTION_MD_BASE + 4)
86
#define OPTION_IDLE2    (OPTION_MD_BASE + 5)
87
#define OPTION_LOWPOWER (OPTION_MD_BASE + 6)
88
#define OPTION_ENHANCED (OPTION_MD_BASE + 7)
89
#define OPTION_REV      (OPTION_MD_BASE + 8)
90
 
91
CONST char *md_shortopts = "bm:prs";
92
struct option md_longopts[] =
93
{
94
  { "mcpu",   required_argument, NULL, OPTION_CPU },
95
  { "mdsp",   required_argument, NULL, OPTION_CPU },
96
  { "mbig",         no_argument, NULL, OPTION_BIG },
97
  { "msmall",       no_argument, NULL, OPTION_SMALL },
98
  { "mmemparm",     no_argument, NULL, OPTION_MEMPARM },
99
  { "mregparm",     no_argument, NULL, OPTION_REGPARM },
100
  { "midle2",       no_argument, NULL, OPTION_IDLE2 },
101
  { "mlowpower",    no_argument, NULL, OPTION_LOWPOWER },
102
  { "menhanced",    no_argument, NULL, OPTION_ENHANCED },
103
  { "mrev",   required_argument, NULL, OPTION_REV },
104
  { NULL, no_argument, NULL, 0 }
105
};
106
 
107
size_t md_longopts_size = sizeof (md_longopts);
108
 
109
 
110
typedef enum
111
  {
112
    M_UNKNOWN, M_IMMED, M_DIRECT, M_REGISTER, M_INDIRECT,
113
    M_IMMED_F, M_PARALLEL, M_HI
114
  }
115
tic4x_addr_mode_t;
116
 
117
typedef struct tic4x_operand
118
  {
119
    tic4x_addr_mode_t mode;     /* Addressing mode.  */
120
    expressionS expr;           /* Expression.  */
121
    int disp;                   /* Displacement for indirect addressing.  */
122
    int aregno;                 /* Aux. register number.  */
123
    LITTLENUM_TYPE fwords[MAX_LITTLENUMS];      /* Float immed. number.  */
124
  }
125
tic4x_operand_t;
126
 
127
typedef struct tic4x_insn
128
  {
129
    char name[TIC4X_NAME_MAX];  /* Mnemonic of instruction.  */
130
    unsigned int in_use;        /* True if in_use.  */
131
    unsigned int parallel;      /* True if parallel instruction.  */
132
    unsigned int nchars;        /* This is always 4 for the C30.  */
133
    unsigned long opcode;       /* Opcode number.  */
134
    expressionS exp;            /* Expression required for relocation.  */
135
    int reloc;                  /* Relocation type required.  */
136
    int pcrel;                  /* True if relocation PC relative.  */
137
    char *pname;                /* Name of instruction in parallel.  */
138
    unsigned int num_operands;  /* Number of operands in total.  */
139
    tic4x_inst_t *inst;         /* Pointer to first template.  */
140
    tic4x_operand_t operands[TIC4X_OPERANDS_MAX];
141
  }
142
tic4x_insn_t;
143
 
144
static tic4x_insn_t the_insn;   /* Info about our instruction.  */
145
static tic4x_insn_t *insn = &the_insn;
146
 
147
static int tic4x_gen_to_words
148
  PARAMS ((FLONUM_TYPE, LITTLENUM_TYPE *, int ));
149
static char *tic4x_atof
150
  PARAMS ((char *, char, LITTLENUM_TYPE * ));
151
static void tic4x_insert_reg
152
  PARAMS ((char *, int ));
153
static void tic4x_insert_sym
154
  PARAMS ((char *, int ));
155
static char *tic4x_expression
156
  PARAMS ((char *, expressionS *));
157
static char *tic4x_expression_abs
158
  PARAMS ((char *, offsetT *));
159
static void tic4x_emit_char
160
  PARAMS ((char, int));
161
static void tic4x_seg_alloc
162
  PARAMS ((char *, segT, int, symbolS *));
163
static void tic4x_asg
164
  PARAMS ((int));
165
static void tic4x_bss
166
  PARAMS ((int));
167
static void tic4x_globl
168
  PARAMS ((int));
169
static void tic4x_cons
170
  PARAMS ((int));
171
static void tic4x_stringer
172
  PARAMS ((int));
173
static void tic4x_eval
174
  PARAMS ((int));
175
static void tic4x_newblock
176
  PARAMS ((int));
177
static void tic4x_sect
178
  PARAMS ((int));
179
static void tic4x_set
180
  PARAMS ((int));
181
static void tic4x_usect
182
  PARAMS ((int));
183
static void tic4x_version
184
  PARAMS ((int));
185
static void tic4x_init_regtable
186
  PARAMS ((void));
187
static void tic4x_init_symbols
188
  PARAMS ((void));
189
static int tic4x_inst_insert (const tic4x_inst_t *);
190
static tic4x_inst_t *tic4x_inst_make
191
  PARAMS ((char *, unsigned long, char *));
192
static int tic4x_inst_add (const tic4x_inst_t *);
193
void tic4x_end
194
  PARAMS ((void));
195
static int tic4x_indirect_parse
196
  PARAMS ((tic4x_operand_t *, const tic4x_indirect_t *));
197
static char *tic4x_operand_parse
198
  PARAMS ((char *, tic4x_operand_t *));
199
static int tic4x_operands_match
200
  PARAMS ((tic4x_inst_t *, tic4x_insn_t *, int));
201
static void tic4x_insn_check
202
  PARAMS ((tic4x_insn_t *));
203
static void tic4x_insn_output
204
  PARAMS ((tic4x_insn_t *));
205
static int tic4x_operands_parse
206
  PARAMS ((char *, tic4x_operand_t *, int ));
207
void tic4x_cleanup
208
  PARAMS ((void));
209
int tic4x_unrecognized_line
210
  PARAMS ((int));
211
static int tic4x_pc_offset
212
  PARAMS ((unsigned int));
213
int tic4x_do_align
214
  PARAMS ((int, const char *, int, int));
215
void tic4x_start_line
216
  PARAMS ((void));
217
arelent *tc_gen_reloc
218
  PARAMS ((asection *, fixS *));
219
 
220
 
221
const pseudo_typeS
222
  md_pseudo_table[] =
223
{
224
  {"align", s_align_bytes, 32},
225
  {"ascii", tic4x_stringer, 1},
226
  {"asciz", tic4x_stringer, 0},
227
  {"asg", tic4x_asg, 0},
228
  {"block", s_space, 4},
229
  {"byte", tic4x_cons, 1},
230
  {"bss", tic4x_bss, 0},
231
  {"copy", s_include, 0},
232
  {"def", tic4x_globl, 0},
233
  {"equ", tic4x_set, 0},
234
  {"eval", tic4x_eval, 0},
235
  {"global", tic4x_globl, 0},
236
  {"globl", tic4x_globl, 0},
237
  {"hword", tic4x_cons, 2},
238
  {"ieee", float_cons, 'i'},
239
  {"int", tic4x_cons, 4},                /* .int allocates 4 bytes.  */
240
  {"ldouble", float_cons, 'e'},
241
  {"newblock", tic4x_newblock, 0},
242
  {"ref", s_ignore, 0},           /* All undefined treated as external.  */
243
  {"set", tic4x_set, 0},
244
  {"sect", tic4x_sect, 1},       /* Define named section.  */
245
  {"space", s_space, 4},
246
  {"string", tic4x_stringer, 0},
247
  {"usect", tic4x_usect, 0},       /* Reserve space in uninit. named sect.  */
248
  {"version", tic4x_version, 0},
249
  {"word", tic4x_cons, 4},       /* .word allocates 4 bytes.  */
250
  {"xdef", tic4x_globl, 0},
251
  {NULL, 0, 0},
252
};
253
 
254
int md_short_jump_size = 4;
255
int md_long_jump_size = 4;
256
 
257
/* This array holds the chars that always start a comment.  If the
258
   pre-processor is disabled, these aren't very useful.  */
259
#ifdef TIC4X_ALT_SYNTAX
260
const char comment_chars[] = ";!";
261
#else
262
const char comment_chars[] = ";";
263
#endif
264
 
265
/* This array holds the chars that only start a comment at the beginning of
266
   a line.  If the line seems to have the form '# 123 filename'
267
   .line and .file directives will appear in the pre-processed output.
268
   Note that input_file.c hand checks for '#' at the beginning of the
269
   first line of the input file.  This is because the compiler outputs
270
   #NO_APP at the beginning of its output.
271
   Also note that comments like this one will always work.  */
272
const char line_comment_chars[] = "#*";
273
 
274
/* We needed an unused char for line separation to work around the
275
   lack of macros, using sed and such.  */
276
const char line_separator_chars[] = "&";
277
 
278
/* Chars that can be used to separate mant from exp in floating point nums.  */
279
const char EXP_CHARS[] = "eE";
280
 
281
/* Chars that mean this number is a floating point constant.  */
282
/* As in 0f12.456 */
283
/* or    0d1.2345e12 */
284
const char FLT_CHARS[] = "fFilsS";
285
 
286
/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
287
   changed in read.c.  Ideally it shouldn't have to know about it at
288
   all, but nothing is ideal around here.  */
289
 
290
/* Flonums returned here.  */
291
extern FLONUM_TYPE generic_floating_point_number;
292
 
293
/* Precision in LittleNums.  */
294
#define MAX_PRECISION (4)       /* Its a bit overkill for us, but the code
295
                                   requires it... */
296
#define S_PRECISION (1)         /* Short float constants 16-bit.  */
297
#define F_PRECISION (2)         /* Float and double types 32-bit.  */
298
#define E_PRECISION (4)         /* Extended precision, 64-bit (real 40-bit). */
299
#define GUARD (2)
300
 
301
/* Turn generic_floating_point_number into a real short/float/double.  */
302
static int
303
tic4x_gen_to_words (flonum, words, precision)
304
     FLONUM_TYPE flonum;
305
     LITTLENUM_TYPE *words;
306
     int precision;
307
{
308
  int return_value = 0;
309
  LITTLENUM_TYPE *p;            /* Littlenum pointer.  */
310
  int mantissa_bits;            /* Bits in mantissa field.  */
311
  int exponent_bits;            /* Bits in exponent field.  */
312
  int exponent;
313
  unsigned int sone;            /* Scaled one.  */
314
  unsigned int sfract;          /* Scaled fraction.  */
315
  unsigned int smant;           /* Scaled mantissa.  */
316
  unsigned int tmp;
317
  unsigned int mover;           /* Mantissa overflow bits */
318
  unsigned int rbit;            /* Round bit. */
319
  int shift;                    /* Shift count.  */
320
 
321
  /* NOTE: Svein Seldal <Svein@dev.seldal.com>
322
     The code in this function is altered slightly to support floats
323
     with 31-bits mantissas, thus the documentation below may be a
324
     little bit inaccurate.
325
 
326
     By Michael P. Hayes <m.hayes@elec.canterbury.ac.nz>
327
     Here is how a generic floating point number is stored using
328
     flonums (an extension of bignums) where p is a pointer to an
329
     array of LITTLENUMs.
330
 
331
     For example 2e-3 is stored with exp = -4 and
332
     bits[0] = 0x0000
333
     bits[1] = 0x0000
334
     bits[2] = 0x4fde
335
     bits[3] = 0x978d
336
     bits[4] = 0x126e
337
     bits[5] = 0x0083
338
     with low = &bits[2], high = &bits[5], and leader = &bits[5].
339
 
340
     This number can be written as
341
     0x0083126e978d4fde.00000000 * 65536**-4  or
342
     0x0.0083126e978d4fde        * 65536**0   or
343
     0x0.83126e978d4fde          * 2**-8   = 2e-3
344
 
345
     Note that low points to the 65536**0 littlenum (bits[2]) and
346
     leader points to the most significant non-zero littlenum
347
     (bits[5]).
348
 
349
     TMS320C3X floating point numbers are a bit of a strange beast.
350
     The 32-bit flavour has the 8 MSBs representing the exponent in
351
     twos complement format (-128 to +127).  There is then a sign bit
352
     followed by 23 bits of mantissa.  The mantissa is expressed in
353
     twos complement format with the binary point after the most
354
     significant non sign bit.  The bit after the binary point is
355
     suppressed since it is the complement of the sign bit.  The
356
     effective mantissa is thus 24 bits.  Zero is represented by an
357
     exponent of -128.
358
 
359
     The 16-bit flavour has the 4 MSBs representing the exponent in
360
     twos complement format (-8 to +7).  There is then a sign bit
361
     followed by 11 bits of mantissa.  The mantissa is expressed in
362
     twos complement format with the binary point after the most
363
     significant non sign bit.  The bit after the binary point is
364
     suppressed since it is the complement of the sign bit.  The
365
     effective mantissa is thus 12 bits.  Zero is represented by an
366
     exponent of -8.  For example,
367
 
368
     number       norm mant m  x  e  s  i    fraction f
369
     +0.500 =>  1.00000000000 -1 -1  0  1  .00000000000   (1 + 0) * 2^(-1)
370
     +0.999 =>  1.11111111111 -1 -1  0  1  .11111111111   (1 + 0.99) * 2^(-1)
371
     +1.000 =>  1.00000000000  0  0  0  1  .00000000000   (1 + 0) * 2^(0)
372
     +1.500 =>  1.10000000000  0  0  0  1  .10000000000   (1 + 0.5) * 2^(0)
373
     +1.999 =>  1.11111111111  0  0  0  1  .11111111111   (1 + 0.9) * 2^(0)
374
     +2.000 =>  1.00000000000  1  1  0  1  .00000000000   (1 + 0) * 2^(1)
375
     +4.000 =>  1.00000000000  2  2  0  1  .00000000000   (1 + 0) * 2^(2)
376
     -0.500 =>  1.00000000000 -1 -1  1  0  .10000000000   (-2 + 0) * 2^(-2)
377
     -1.000 =>  1.00000000000  0 -1  1  0  .00000000000   (-2 + 0) * 2^(-1)
378
     -1.500 =>  1.10000000000  0  0  1  0  .10000000000   (-2 + 0.5) * 2^(0)
379
     -1.999 =>  1.11111111111  0  0  1  0  .00000000001   (-2 + 0.11) * 2^(0)
380
     -2.000 =>  1.00000000000  1  1  1  0  .00000000000   (-2 + 0) * 2^(0)
381
     -4.000 =>  1.00000000000  2  1  1  0  .00000000000   (-2 + 0) * 2^(1)
382
 
383
     where e is the exponent, s is the sign bit, i is the implied bit,
384
     and f is the fraction stored in the mantissa field.
385
 
386
     num = (1 + f) * 2^x   =  m * 2^e if s = 0
387
     num = (-2 + f) * 2^x  = -m * 2^e if s = 1
388
     where 0 <= f < 1.0  and 1.0 <= m < 2.0
389
 
390
     The fraction (f) and exponent (e) fields for the TMS320C3X format
391
     can be derived from the normalised mantissa (m) and exponent (x) using:
392
 
393
     f = m - 1, e = x       if s = 0
394
     f = 2 - m, e = x       if s = 1 and m != 1.0
395
     f = 0,     e = x - 1   if s = 1 and m = 1.0
396
     f = 0,     e = -8      if m = 0
397
 
398
 
399
     OK, the other issue we have to consider is rounding since the
400
     mantissa has a much higher potential precision than what we can
401
     represent.  To do this we add half the smallest storable fraction.
402
     We then have to renormalise the number to allow for overflow.
403
 
404
     To convert a generic flonum into a TMS320C3X floating point
405
     number, here's what we try to do....
406
 
407
     The first thing is to generate a normalised mantissa (m) where
408
     1.0 <= m < 2 and to convert the exponent from base 16 to base 2.
409
     We desire the binary point to be placed after the most significant
410
     non zero bit.  This process is done in two steps: firstly, the
411
     littlenum with the most significant non zero bit is located (this
412
     is done for us since leader points to this littlenum) and the
413
     binary point (which is currently after the LSB of the littlenum
414
     pointed to by low) is moved to before the MSB of the littlenum
415
     pointed to by leader.  This requires the exponent to be adjusted
416
     by leader - low + 1.  In the earlier example, the new exponent is
417
     thus -4 + (5 - 2 + 1) = 0 (base 65536).  We now need to convert
418
     the exponent to base 2 by multiplying the exponent by 16 (log2
419
     65536).  The exponent base 2 is thus also zero.
420
 
421
     The second step is to hunt for the most significant non zero bit
422
     in the leader littlenum.  We do this by left shifting a copy of
423
     the leader littlenum until bit 16 is set (0x10000) and counting
424
     the number of shifts, S, required.  The number of shifts then has to
425
     be added to correct the exponent (base 2).  For our example, this
426
     will require 9 shifts and thus our normalised exponent (base 2) is
427
 
428
     littlenum is 1, thus requiring 16 shifts.
429
 
430
     We now have to left shift the other littlenums by the same amount,
431
     propagating the shifted bits into the more significant littlenums.
432
     To save a lot of unnecessary shifting we only have to consider
433
     two or three littlenums, since the greatest number of mantissa
434
     bits required is 24 + 1 rounding bit.  While two littlenums
435
     provide 32 bits of precision, the most significant littlenum
436
     may only contain a single significant bit  and thus an extra
437
     littlenum is required.
438
 
439
     Denoting the number of bits in the fraction field as F, we require
440
     G = F + 2 bits (one extra bit is for rounding, the other gets
441
     suppressed).  Say we required S shifts to find the most
442
     significant bit in the leader littlenum, the number of left shifts
443
     required to move this bit into bit position G - 1 is L = G + S - 17.
444
     Note that this shift count may be negative for the short floating
445
     point flavour (where F = 11 and thus G = 13 and potentially S < 3).
446
     If L > 0 we have to shunt the next littlenum into position.  Bit
447
     15 (the MSB) of the next littlenum needs to get moved into position
448
     L - 1 (If L > 15 we need all the bits of this littlenum and
449
     some more from the next one.).  We subtract 16 from L and use this
450
     as the left shift count;  the resultant value we or with the
451
     previous result.  If L > 0, we repeat this operation.   */
452
 
453
  if (precision != S_PRECISION)
454
    words[1] = 0x0000;
455
  if (precision == E_PRECISION)
456
    words[2] = words[3] = 0x0000;
457
 
458
  /* 0.0e0 or NaN seen.  */
459
  if (flonum.low > flonum.leader  /* = 0.0e0 */
460
      || flonum.sign == 0) /* = NaN */
461
    {
462
      if(flonum.sign == 0)
463
        as_bad ("Nan, using zero.");
464
      words[0] = 0x8000;
465
      return return_value;
466
    }
467
 
468
  if (flonum.sign == 'P')
469
    {
470
      /* +INF:  Replace with maximum float.  */
471
      if (precision == S_PRECISION)
472
        words[0] = 0x77ff;
473
      else
474
        {
475
          words[0] = 0x7f7f;
476
          words[1] = 0xffff;
477
        }
478
      if (precision == E_PRECISION)
479
        {
480
          words[2] = 0x7fff;
481
          words[3] = 0xffff;
482
        }
483
      return return_value;
484
    }
485
  else if (flonum.sign == 'N')
486
    {
487
      /* -INF:  Replace with maximum float.  */
488
      if (precision == S_PRECISION)
489
        words[0] = 0x7800;
490
      else
491
        words[0] = 0x7f80;
492
      if (precision == E_PRECISION)
493
        words[2] = 0x8000;
494
      return return_value;
495
    }
496
 
497
  exponent = (flonum.exponent + flonum.leader - flonum.low + 1) * 16;
498
 
499
  if (!(tmp = *flonum.leader))
500
    abort ();                   /* Hmmm.  */
501
  shift = 0;                     /* Find position of first sig. bit.  */
502
  while (tmp >>= 1)
503
    shift++;
504
  exponent -= (16 - shift);     /* Adjust exponent.  */
505
 
506
  if (precision == S_PRECISION) /* Allow 1 rounding bit.  */
507
    {
508
      exponent_bits = 4;
509
      mantissa_bits = 11;
510
    }
511
  else if(precision == F_PRECISION)
512
    {
513
      exponent_bits = 8;
514
      mantissa_bits = 23;
515
    }
516
  else /* E_PRECISION */
517
    {
518
      exponent_bits = 8;
519
      mantissa_bits = 31;
520
    }
521
 
522
  shift = mantissa_bits - shift;
523
 
524
  smant = 0;
525
  mover = 0;
526
  rbit = 0;
527
  /* Store the mantissa data into smant and the roundbit into rbit */
528
  for (p = flonum.leader; p >= flonum.low && shift > -16; p--)
529
    {
530
      tmp = shift >= 0 ? *p << shift : *p >> -shift;
531
      rbit = shift < 0 ? ((*p >> (-shift-1)) & 0x1) : 0;
532
      smant |= tmp;
533
      shift -= 16;
534
    }
535
 
536
  /* OK, we've got our scaled mantissa so let's round it up */
537
  if(rbit)
538
    {
539
      /* If the mantissa is going to overflow when added, lets store
540
         the extra bit in mover. -- A special case exists when
541
         mantissa_bits is 31 (E_PRECISION). Then the first test cannot
542
         be trusted, as result is host-dependent, thus the second
543
         test. */
544
      if( smant == ((unsigned)(1<<(mantissa_bits+1))-1)
545
          || smant == (unsigned)-1 )  /* This is to catch E_PRECISION cases */
546
        mover=1;
547
      smant++;
548
    }
549
 
550
  /* Get the scaled one value */
551
  sone = (1 << (mantissa_bits));
552
 
553
  /* The number may be unnormalised so renormalise it...  */
554
  if(mover)
555
    {
556
      smant >>= 1;
557
      smant |= sone; /* Insert the bit from mover into smant */
558
      exponent++;
559
    }
560
 
561
  /* The binary point is now between bit positions 11 and 10 or 23 and 22,
562
     i.e., between mantissa_bits - 1 and mantissa_bits - 2 and the
563
     bit at mantissa_bits - 1 should be set.  */
564
  if (!(sone&smant))
565
    abort ();                   /* Ooops.  */
566
 
567
  if (flonum.sign == '+')
568
    sfract = smant - sone;      /* smant - 1.0.  */
569
  else
570
    {
571
      /* This seems to work.  */
572
      if (smant == sone)
573
        {
574
          exponent--;
575
          sfract = 0;
576
        }
577
      else
578
        {
579
          sfract = -smant & (sone-1);   /* 2.0 - smant.  */
580
        }
581
      sfract |= sone;           /* Insert sign bit.  */
582
    }
583
 
584
  if (abs (exponent) >= (1 << (exponent_bits - 1)))
585
    as_bad ("Cannot represent exponent in %d bits", exponent_bits);
586
 
587
  /* Force exponent to fit in desired field width.  */
588
  exponent &= (1 << (exponent_bits)) - 1;
589
 
590
  if (precision == E_PRECISION)
591
    {
592
      /* Map the float part first (100% equal format as F_PRECISION) */
593
      words[0]  = exponent << (mantissa_bits+1-24);
594
      words[0] |= sfract >> 24;
595
      words[1]  = sfract >> 8;
596
 
597
      /* Map the mantissa in the next */
598
      words[2]  = sfract >> 16;
599
      words[3]  = sfract & 0xffff;
600
    }
601
  else
602
    {
603
      /* Insert the exponent data into the word */
604
      sfract |= exponent << (mantissa_bits+1);
605
 
606
      if (precision == S_PRECISION)
607
        words[0] = sfract;
608
      else
609
        {
610
          words[0] = sfract >> 16;
611
          words[1] = sfract & 0xffff;
612
        }
613
    }
614
 
615
  return return_value;
616
}
617
 
618
/* Returns pointer past text consumed.  */
619
static char *
620
tic4x_atof (str, what_kind, words)
621
     char *str;
622
     char what_kind;
623
     LITTLENUM_TYPE *words;
624
{
625
  /* Extra bits for zeroed low-order bits.  The 1st MAX_PRECISION are
626
     zeroed, the last contain flonum bits.  */
627
  static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
628
  char *return_value;
629
  /* Number of 16-bit words in the format.  */
630
  int precision;
631
  FLONUM_TYPE save_gen_flonum;
632
 
633
  /* We have to save the generic_floating_point_number because it
634
     contains storage allocation about the array of LITTLENUMs where
635
     the value is actually stored.  We will allocate our own array of
636
     littlenums below, but have to restore the global one on exit.  */
637
  save_gen_flonum = generic_floating_point_number;
638
 
639
  return_value = str;
640
  generic_floating_point_number.low = bits + MAX_PRECISION;
641
  generic_floating_point_number.high = NULL;
642
  generic_floating_point_number.leader = NULL;
643
  generic_floating_point_number.exponent = 0;
644
  generic_floating_point_number.sign = '\0';
645
 
646
  /* Use more LittleNums than seems necessary: the highest flonum may
647
     have 15 leading 0 bits, so could be useless.  */
648
 
649
  memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
650
 
651
  switch (what_kind)
652
    {
653
    case 's':
654
    case 'S':
655
      precision = S_PRECISION;
656
      break;
657
 
658
    case 'd':
659
    case 'D':
660
    case 'f':
661
    case 'F':
662
      precision = F_PRECISION;
663
      break;
664
 
665
    case 'E':
666
    case 'e':
667
      precision = E_PRECISION;
668
      break;
669
 
670
    default:
671
      as_bad ("Invalid floating point number");
672
      return (NULL);
673
    }
674
 
675
  generic_floating_point_number.high
676
    = generic_floating_point_number.low + precision - 1 + GUARD;
677
 
678
  if (atof_generic (&return_value, ".", EXP_CHARS,
679
                    &generic_floating_point_number))
680
    {
681
      as_bad ("Invalid floating point number");
682
      return (NULL);
683
    }
684
 
685
  tic4x_gen_to_words (generic_floating_point_number,
686
                    words, precision);
687
 
688
  /* Restore the generic_floating_point_number's storage alloc (and
689
     everything else).  */
690
  generic_floating_point_number = save_gen_flonum;
691
 
692
  return return_value;
693
}
694
 
695
static void
696
tic4x_insert_reg (regname, regnum)
697
     char *regname;
698
     int regnum;
699
{
700
  char buf[32];
701
  int i;
702
 
703
  symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
704
                                   &zero_address_frag));
705
  for (i = 0; regname[i]; i++)
706
    buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
707
  buf[i] = '\0';
708
 
709
  symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
710
                                   &zero_address_frag));
711
}
712
 
713
static void
714
tic4x_insert_sym (symname, value)
715
     char *symname;
716
     int value;
717
{
718
  symbolS *symbolP;
719
 
720
  symbolP = symbol_new (symname, absolute_section,
721
                        (valueT) value, &zero_address_frag);
722
  SF_SET_LOCAL (symbolP);
723
  symbol_table_insert (symbolP);
724
}
725
 
726
static char *
727
tic4x_expression (str, exp)
728
     char *str;
729
     expressionS *exp;
730
{
731
  char *s;
732
  char *t;
733
 
734
  t = input_line_pointer;       /* Save line pointer.  */
735
  input_line_pointer = str;
736
  expression (exp);
737
  s = input_line_pointer;
738
  input_line_pointer = t;       /* Restore line pointer.  */
739
  return s;                     /* Return pointer to where parsing stopped.  */
740
}
741
 
742
static char *
743
tic4x_expression_abs (str, value)
744
     char *str;
745
     offsetT *value;
746
{
747
  char *s;
748
  char *t;
749
 
750
  t = input_line_pointer;       /* Save line pointer.  */
751
  input_line_pointer = str;
752
  *value = get_absolute_expression ();
753
  s = input_line_pointer;
754
  input_line_pointer = t;       /* Restore line pointer.  */
755
  return s;
756
}
757
 
758
static void
759
tic4x_emit_char (c,b)
760
     char c;
761
     int b;
762
{
763
  expressionS exp;
764
 
765
  exp.X_op = O_constant;
766
  exp.X_add_number = c;
767
  emit_expr (&exp, b);
768
}
769
 
770
static void
771
tic4x_seg_alloc (name, seg, size, symbolP)
772
     char *name ATTRIBUTE_UNUSED;
773
     segT seg ATTRIBUTE_UNUSED;
774
     int size;
775
     symbolS *symbolP;
776
{
777
  /* Note that the size is in words
778
     so we multiply it by 4 to get the number of bytes to allocate.  */
779
 
780
  /* If we have symbol:  .usect  ".fred", size etc.,
781
     the symbol needs to point to the first location reserved
782
     by the pseudo op.  */
783
 
784
  if (size)
785
    {
786
      char *p;
787
 
788
      p = frag_var (rs_fill, 1, 1, (relax_substateT) 0,
789
                    (symbolS *) symbolP,
790
                    size * OCTETS_PER_BYTE, (char *) 0);
791
      *p = 0;
792
    }
793
}
794
 
795
/* .asg ["]character-string["], symbol */
796
static void
797
tic4x_asg (x)
798
     int x ATTRIBUTE_UNUSED;
799
{
800
  char c;
801
  char *name;
802
  char *str;
803
  char *tmp;
804
 
805
  SKIP_WHITESPACE ();
806
  str = input_line_pointer;
807
 
808
  /* Skip string expression.  */
809
  while (*input_line_pointer != ',' && *input_line_pointer)
810
    input_line_pointer++;
811
  if (*input_line_pointer != ',')
812
    {
813
      as_bad ("Comma expected\n");
814
      return;
815
    }
816
  *input_line_pointer++ = '\0';
817
  name = input_line_pointer;
818
  c = get_symbol_end ();        /* Get terminator.  */
819
  tmp = xmalloc (strlen (str) + 1);
820
  strcpy (tmp, str);
821
  str = tmp;
822
  tmp = xmalloc (strlen (name) + 1);
823
  strcpy (tmp, name);
824
  name = tmp;
825
  if (hash_find (tic4x_asg_hash, name))
826
    hash_replace (tic4x_asg_hash, name, (PTR) str);
827
  else
828
    hash_insert (tic4x_asg_hash, name, (PTR) str);
829
  *input_line_pointer = c;
830
  demand_empty_rest_of_line ();
831
}
832
 
833
/* .bss symbol, size  */
834
static void
835
tic4x_bss (x)
836
     int x ATTRIBUTE_UNUSED;
837
{
838
  char c;
839
  char *name;
840
  char *p;
841
  offsetT size;
842
  segT current_seg;
843
  subsegT current_subseg;
844
  symbolS *symbolP;
845
 
846
  current_seg = now_seg;        /* Save current seg.  */
847
  current_subseg = now_subseg;  /* Save current subseg.  */
848
 
849
  SKIP_WHITESPACE ();
850
  name = input_line_pointer;
851
  c = get_symbol_end ();        /* Get terminator.  */
852
  if (c != ',')
853
    {
854
      as_bad (".bss size argument missing\n");
855
      return;
856
    }
857
 
858
  input_line_pointer =
859
    tic4x_expression_abs (++input_line_pointer, &size);
860
  if (size < 0)
861
    {
862
      as_bad (".bss size %ld < 0!", (long) size);
863
      return;
864
    }
865
  subseg_set (bss_section, 0);
866
  symbolP = symbol_find_or_make (name);
867
 
868
  if (S_GET_SEGMENT (symbolP) == bss_section)
869
    symbol_get_frag (symbolP)->fr_symbol = 0;
870
 
871
  symbol_set_frag (symbolP, frag_now);
872
 
873
  p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
874
                size * OCTETS_PER_BYTE, (char *) 0);
875
  *p = 0;                        /* Fill char.  */
876
 
877
  S_SET_SEGMENT (symbolP, bss_section);
878
 
879
  /* The symbol may already have been created with a preceding
880
     ".globl" directive -- be careful not to step on storage class
881
     in that case.  Otherwise, set it to static.  */
882
  if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
883
    S_SET_STORAGE_CLASS (symbolP, C_STAT);
884
 
885
  subseg_set (current_seg, current_subseg); /* Restore current seg.  */
886
  demand_empty_rest_of_line ();
887
}
888
 
889
static void
890
tic4x_globl (ignore)
891
     int ignore ATTRIBUTE_UNUSED;
892
{
893
  char *name;
894
  int c;
895
  symbolS *symbolP;
896
 
897
  do
898
    {
899
      name = input_line_pointer;
900
      c = get_symbol_end ();
901
      symbolP = symbol_find_or_make (name);
902
      *input_line_pointer = c;
903
      SKIP_WHITESPACE ();
904
      S_SET_STORAGE_CLASS (symbolP, C_EXT);
905
      if (c == ',')
906
        {
907
          input_line_pointer++;
908
          SKIP_WHITESPACE ();
909
          if (*input_line_pointer == '\n')
910
            c = '\n';
911
        }
912
    }
913
  while (c == ',');
914
 
915
  demand_empty_rest_of_line ();
916
}
917
 
918
/* Handle .byte, .word. .int, .long */
919
static void
920
tic4x_cons (bytes)
921
     int bytes;
922
{
923
  register unsigned int c;
924
  do
925
    {
926
      SKIP_WHITESPACE ();
927
      if (*input_line_pointer == '"')
928
        {
929
          input_line_pointer++;
930
          while (is_a_char (c = next_char_of_string ()))
931
            tic4x_emit_char (c, 4);
932
          know (input_line_pointer[-1] == '\"');
933
        }
934
      else
935
        {
936
          expressionS exp;
937
 
938
          input_line_pointer = tic4x_expression (input_line_pointer, &exp);
939
          if (exp.X_op == O_constant)
940
            {
941
              switch (bytes)
942
                {
943
                case 1:
944
                  exp.X_add_number &= 255;
945
                  break;
946
                case 2:
947
                  exp.X_add_number &= 65535;
948
                  break;
949
                }
950
            }
951
          /* Perhaps we should disallow .byte and .hword with
952
             a non constant expression that will require relocation.  */
953
          emit_expr (&exp, 4);
954
        }
955
    }
956
  while (*input_line_pointer++ == ',');
957
 
958
  input_line_pointer--;         /* Put terminator back into stream.  */
959
  demand_empty_rest_of_line ();
960
}
961
 
962
/* Handle .ascii, .asciz, .string */
963
static void
964
tic4x_stringer (append_zero)
965
     int append_zero; /*ex: bytes */
966
{
967
  int bytes;
968
  register unsigned int c;
969
 
970
  bytes = 0;
971
  do
972
    {
973
      SKIP_WHITESPACE ();
974
      if (*input_line_pointer == '"')
975
        {
976
          input_line_pointer++;
977
          while (is_a_char (c = next_char_of_string ()))
978
            {
979
              tic4x_emit_char (c, 1);
980
              bytes++;
981
            }
982
 
983
          if (append_zero)
984
            {
985
              tic4x_emit_char (c, 1);
986
              bytes++;
987
            }
988
 
989
          know (input_line_pointer[-1] == '\"');
990
        }
991
      else
992
        {
993
          expressionS exp;
994
 
995
          input_line_pointer = tic4x_expression (input_line_pointer, &exp);
996
          if (exp.X_op != O_constant)
997
            {
998
              as_bad("Non-constant symbols not allowed\n");
999
              return;
1000
            }
1001
          exp.X_add_number &= 255; /* Limit numeber to 8-bit */
1002
          emit_expr (&exp, 1);
1003
          bytes++;
1004
        }
1005
    }
1006
  while (*input_line_pointer++ == ',');
1007
 
1008
  /* Fill out the rest of the expression with 0's to fill up a full word */
1009
  if ( bytes&0x3 )
1010
    tic4x_emit_char (0, 4-(bytes&0x3));
1011
 
1012
  input_line_pointer--;         /* Put terminator back into stream.  */
1013
  demand_empty_rest_of_line ();
1014
}
1015
 
1016
/* .eval expression, symbol */
1017
static void
1018
tic4x_eval (x)
1019
     int x ATTRIBUTE_UNUSED;
1020
{
1021
  char c;
1022
  offsetT value;
1023
  char *name;
1024
 
1025
  SKIP_WHITESPACE ();
1026
  input_line_pointer =
1027
    tic4x_expression_abs (input_line_pointer, &value);
1028
  if (*input_line_pointer++ != ',')
1029
    {
1030
      as_bad ("Symbol missing\n");
1031
      return;
1032
    }
1033
  name = input_line_pointer;
1034
  c = get_symbol_end ();        /* Get terminator.  */
1035
  demand_empty_rest_of_line ();
1036
  tic4x_insert_sym (name, value);
1037
}
1038
 
1039
/* Reset local labels.  */
1040
static void
1041
tic4x_newblock (x)
1042
     int x ATTRIBUTE_UNUSED;
1043
{
1044
  dollar_label_clear ();
1045
}
1046
 
1047
/* .sect "section-name" [, value] */
1048
/* .sect ["]section-name[:subsection-name]["] [, value] */
1049
static void
1050
tic4x_sect (x)
1051
     int x ATTRIBUTE_UNUSED;
1052
{
1053
  char c;
1054
  char *section_name;
1055
  char *subsection_name;
1056
  char *name;
1057
  segT seg;
1058
  offsetT num;
1059
 
1060
  SKIP_WHITESPACE ();
1061
  if (*input_line_pointer == '"')
1062
    input_line_pointer++;
1063
  section_name = input_line_pointer;
1064
  c = get_symbol_end ();        /* Get terminator.  */
1065
  input_line_pointer++;         /* Skip null symbol terminator.  */
1066
  name = xmalloc (input_line_pointer - section_name + 1);
1067
  strcpy (name, section_name);
1068
 
1069
  /* TI C from version 5.0 allows a section name to contain a
1070
     subsection name as well. The subsection name is separated by a
1071
     ':' from the section name.  Currently we scan the subsection
1072
     name and discard it.
1073
     Volker Kuhlmann  <v.kuhlmann@elec.canterbury.ac.nz>.  */
1074
  if (c == ':')
1075
    {
1076
      subsection_name = input_line_pointer;
1077
      c = get_symbol_end ();    /* Get terminator.  */
1078
      input_line_pointer++;     /* Skip null symbol terminator.  */
1079
      as_warn (".sect: subsection name ignored");
1080
    }
1081
 
1082
  /* We might still have a '"' to discard, but the character after a
1083
     symbol name will be overwritten with a \0 by get_symbol_end()
1084
     [VK].  */
1085
 
1086
  if (c == ',')
1087
    input_line_pointer =
1088
      tic4x_expression_abs (input_line_pointer, &num);
1089
  else if (*input_line_pointer == ',')
1090
    {
1091
      input_line_pointer =
1092
        tic4x_expression_abs (++input_line_pointer, &num);
1093
    }
1094
  else
1095
    num = 0;
1096
 
1097
  seg = subseg_new (name, num);
1098
  if (line_label != NULL)
1099
    {
1100
      S_SET_SEGMENT (line_label, seg);
1101
      symbol_set_frag (line_label, frag_now);
1102
    }
1103
 
1104
  if (bfd_get_section_flags (stdoutput, seg) == SEC_NO_FLAGS)
1105
    {
1106
      if (!bfd_set_section_flags (stdoutput, seg, SEC_DATA))
1107
        as_warn ("Error setting flags for \"%s\": %s", name,
1108
                 bfd_errmsg (bfd_get_error ()));
1109
    }
1110
 
1111
  /* If the last character overwritten by get_symbol_end() was an
1112
     end-of-line, we must restore it or the end of the line will not be
1113
     recognised and scanning extends into the next line, stopping with
1114
     an error (blame Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
1115
     if this is not true).  */
1116
  if (is_end_of_line[(unsigned char) c])
1117
    *(--input_line_pointer) = c;
1118
 
1119
  demand_empty_rest_of_line ();
1120
}
1121
 
1122
/* symbol[:] .set value  or  .set symbol, value */
1123
static void
1124
tic4x_set (x)
1125
     int x ATTRIBUTE_UNUSED;
1126
{
1127
  symbolS *symbolP;
1128
 
1129
  SKIP_WHITESPACE ();
1130
  if ((symbolP = line_label) == NULL)
1131
    {
1132
      char c;
1133
      char *name;
1134
 
1135
      name = input_line_pointer;
1136
      c = get_symbol_end ();    /* Get terminator.  */
1137
      if (c != ',')
1138
        {
1139
          as_bad (".set syntax invalid\n");
1140
          ignore_rest_of_line ();
1141
          return;
1142
        }
1143
      ++input_line_pointer;
1144
      symbolP = symbol_find_or_make (name);
1145
    }
1146
  else
1147
    symbol_table_insert (symbolP);
1148
 
1149
  pseudo_set (symbolP);
1150
  demand_empty_rest_of_line ();
1151
}
1152
 
1153
/* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
1154
static void
1155
tic4x_usect (x)
1156
     int x ATTRIBUTE_UNUSED;
1157
{
1158
  char c;
1159
  char *name;
1160
  char *section_name;
1161
  segT seg;
1162
  offsetT size, alignment_flag;
1163
  segT current_seg;
1164
  subsegT current_subseg;
1165
 
1166
  current_seg = now_seg;        /* save current seg.  */
1167
  current_subseg = now_subseg;  /* save current subseg.  */
1168
 
1169
  SKIP_WHITESPACE ();
1170
  if (*input_line_pointer == '"')
1171
    input_line_pointer++;
1172
  section_name = input_line_pointer;
1173
  c = get_symbol_end ();        /* Get terminator.  */
1174
  input_line_pointer++;         /* Skip null symbol terminator.  */
1175
  name = xmalloc (input_line_pointer - section_name + 1);
1176
  strcpy (name, section_name);
1177
 
1178
  if (c == ',')
1179
    input_line_pointer =
1180
      tic4x_expression_abs (input_line_pointer, &size);
1181
  else if (*input_line_pointer == ',')
1182
    {
1183
      input_line_pointer =
1184
        tic4x_expression_abs (++input_line_pointer, &size);
1185
    }
1186
  else
1187
    size = 0;
1188
 
1189
  /* Read a possibly present third argument (alignment flag) [VK].  */
1190
  if (*input_line_pointer == ',')
1191
    {
1192
      input_line_pointer =
1193
        tic4x_expression_abs (++input_line_pointer, &alignment_flag);
1194
    }
1195
  else
1196
    alignment_flag = 0;
1197
  if (alignment_flag)
1198
    as_warn (".usect: non-zero alignment flag ignored");
1199
 
1200
  seg = subseg_new (name, 0);
1201
  if (line_label != NULL)
1202
    {
1203
      S_SET_SEGMENT (line_label, seg);
1204
      symbol_set_frag (line_label, frag_now);
1205
      S_SET_VALUE (line_label, frag_now_fix ());
1206
    }
1207
  seg_info (seg)->bss = 1;      /* Uninitialised data.  */
1208
  if (!bfd_set_section_flags (stdoutput, seg, SEC_ALLOC))
1209
    as_warn ("Error setting flags for \"%s\": %s", name,
1210
             bfd_errmsg (bfd_get_error ()));
1211
  tic4x_seg_alloc (name, seg, size, line_label);
1212
 
1213
  if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1214
    S_SET_STORAGE_CLASS (line_label, C_STAT);
1215
 
1216
  subseg_set (current_seg, current_subseg);     /* Restore current seg.  */
1217
  demand_empty_rest_of_line ();
1218
}
1219
 
1220
/* .version cpu-version.  */
1221
static void
1222
tic4x_version (x)
1223
     int x ATTRIBUTE_UNUSED;
1224
{
1225
  offsetT temp;
1226
 
1227
  input_line_pointer =
1228
    tic4x_expression_abs (input_line_pointer, &temp);
1229
  if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp))
1230
    as_bad ("This assembler does not support processor generation %ld",
1231
            (long) temp);
1232
 
1233
  if (tic4x_cpu && temp != (offsetT) tic4x_cpu)
1234
    as_warn ("Changing processor generation on fly not supported...");
1235
  tic4x_cpu = temp;
1236
  demand_empty_rest_of_line ();
1237
}
1238
 
1239
static void
1240
tic4x_init_regtable ()
1241
{
1242
  unsigned int i;
1243
 
1244
  for (i = 0; i < tic3x_num_registers; i++)
1245
    tic4x_insert_reg (tic3x_registers[i].name,
1246
                    tic3x_registers[i].regno);
1247
 
1248
  if (IS_CPU_TIC4X (tic4x_cpu))
1249
    {
1250
      /* Add additional Tic4x registers, overriding some C3x ones.  */
1251
      for (i = 0; i < tic4x_num_registers; i++)
1252
        tic4x_insert_reg (tic4x_registers[i].name,
1253
                        tic4x_registers[i].regno);
1254
    }
1255
}
1256
 
1257
static void
1258
tic4x_init_symbols ()
1259
{
1260
  /* The TI tools accept case insensitive versions of these symbols,
1261
     we don't !
1262
 
1263
     For TI C/Asm 5.0
1264
 
1265
     .TMS320xx       30,31,32,40,or 44       set according to -v flag
1266
     .C3X or .C3x    1 or 0                  1 if -v30,-v31,or -v32
1267
     .C30            1 or 0                  1 if -v30
1268
     .C31            1 or 0                  1 if -v31
1269
     .C32            1 or 0                  1 if -v32
1270
     .C4X or .C4x    1 or 0                  1 if -v40, or -v44
1271
     .C40            1 or 0                  1 if -v40
1272
     .C44            1 or 0                  1 if -v44
1273
 
1274
     .REGPARM 1 or 0                  1 if -mr option used
1275
     .BIGMODEL        1 or 0                  1 if -mb option used
1276
 
1277
     These symbols are currently supported but will be removed in a
1278
     later version:
1279
     .TMS320C30      1 or 0                  1 if -v30,-v31,or -v32
1280
     .TMS320C31      1 or 0                  1 if -v31
1281
     .TMS320C32      1 or 0                  1 if -v32
1282
     .TMS320C40      1 or 0                  1 if -v40, or -v44
1283
     .TMS320C44      1 or 0                  1 if -v44
1284
 
1285
     Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
1286
     1997, SPRU035C, p. 3-17/3-18.  */
1287
  tic4x_insert_sym (".REGPARM", tic4x_reg_args);
1288
  tic4x_insert_sym (".MEMPARM", !tic4x_reg_args);
1289
  tic4x_insert_sym (".BIGMODEL", tic4x_big_model);
1290
  tic4x_insert_sym (".C30INTERRUPT", 0);
1291
  tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu);
1292
  tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1293
  tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1294
  tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
1295
  tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
1296
  /* Do we need to have the following symbols also in lower case?  */
1297
  tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1298
  tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
1299
  tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31);
1300
  tic4x_insert_sym (".tms320C31", tic4x_cpu == 31);
1301
  tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32);
1302
  tic4x_insert_sym (".tms320C32", tic4x_cpu == 32);
1303
  tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33);
1304
  tic4x_insert_sym (".tms320C33", tic4x_cpu == 33);
1305
  tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1306
  tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
1307
  tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44);
1308
  tic4x_insert_sym (".tms320C44", tic4x_cpu == 44);
1309
  tic4x_insert_sym (".TMX320C40", 0);    /* C40 first pass silicon ?  */
1310
  tic4x_insert_sym (".tmx320C40", 0);
1311
}
1312
 
1313
/* Insert a new instruction template into hash table.  */
1314
static int
1315
tic4x_inst_insert (const tic4x_inst_t *inst)
1316
{
1317
  static char prev_name[16];
1318
  const char *retval = NULL;
1319
 
1320
  /* Only insert the first name if have several similar entries.  */
1321
  if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0')
1322
    return 1;
1323
 
1324
  retval = hash_insert (tic4x_op_hash, inst->name, (PTR) inst);
1325
  if (retval != NULL)
1326
    fprintf (stderr, "internal error: can't hash `%s': %s\n",
1327
             inst->name, retval);
1328
  else
1329
    strcpy (prev_name, inst->name);
1330
  return retval == NULL;
1331
}
1332
 
1333
/* Make a new instruction template.  */
1334
static tic4x_inst_t *
1335
tic4x_inst_make (name, opcode, args)
1336
     char *name;
1337
     unsigned long opcode;
1338
     char *args;
1339
{
1340
  static tic4x_inst_t *insts = NULL;
1341
  static char *names = NULL;
1342
  static int index = 0;
1343
 
1344
  if (insts == NULL)
1345
    {
1346
      /* Allocate memory to store name strings.  */
1347
      names = (char *) xmalloc (sizeof (char) * 8192);
1348
      /* Allocate memory for additional insts.  */
1349
      insts = (tic4x_inst_t *)
1350
        xmalloc (sizeof (tic4x_inst_t) * 1024);
1351
    }
1352
  insts[index].name = names;
1353
  insts[index].opcode = opcode;
1354
  insts[index].opmask = 0xffffffff;
1355
  insts[index].args = args;
1356
  index++;
1357
 
1358
  do
1359
    *names++ = *name++;
1360
  while (*name);
1361
  *names++ = '\0';
1362
 
1363
  return &insts[index - 1];
1364
}
1365
 
1366
/* Add instruction template, creating dynamic templates as required.  */
1367
static int
1368
tic4x_inst_add (const tic4x_inst_t *insts)
1369
{
1370
  char *s = insts->name;
1371
  char *d;
1372
  unsigned int i;
1373
  int ok = 1;
1374
  char name[16];
1375
 
1376
  d = name;
1377
 
1378
  /* We do not care about INSNs that is not a part of our
1379
     oplevel setting */
1380
  if (!insts->oplevel & tic4x_oplevel)
1381
    return ok;
1382
 
1383
  while (1)
1384
    {
1385
      switch (*s)
1386
        {
1387
        case 'B':
1388
        case 'C':
1389
          /* Dynamically create all the conditional insts.  */
1390
          for (i = 0; i < tic4x_num_conds; i++)
1391
            {
1392
              tic4x_inst_t *inst;
1393
              int k = 0;
1394
              char *c = tic4x_conds[i].name;
1395
              char *e = d;
1396
 
1397
              while (*c)
1398
                *e++ = *c++;
1399
              c = s + 1;
1400
              while (*c)
1401
                *e++ = *c++;
1402
              *e = '\0';
1403
 
1404
              /* If instruction found then have already processed it.  */
1405
              if (hash_find (tic4x_op_hash, name))
1406
                return 1;
1407
 
1408
              do
1409
                {
1410
                  inst = tic4x_inst_make (name, insts[k].opcode +
1411
                                        (tic4x_conds[i].cond <<
1412
                                         (*s == 'B' ? 16 : 23)),
1413
                                        insts[k].args);
1414
                  if (k == 0)    /* Save strcmp() with following func.  */
1415
                    ok &= tic4x_inst_insert (inst);
1416
                  k++;
1417
                }
1418
              while (!strcmp (insts->name,
1419
                              insts[k].name));
1420
            }
1421
          return ok;
1422
          break;
1423
 
1424
        case '\0':
1425
          return tic4x_inst_insert (insts);
1426
          break;
1427
 
1428
        default:
1429
          *d++ = *s++;
1430
          break;
1431
        }
1432
    }
1433
}
1434
 
1435
/* This function is called once, at assembler startup time.  It should
1436
   set up all the tables, etc., that the MD part of the assembler will
1437
   need.  */
1438
void
1439
md_begin ()
1440
{
1441
  int ok = 1;
1442
  unsigned int i;
1443
 
1444
  /* Setup the proper opcode level according to the
1445
     commandline parameters */
1446
  tic4x_oplevel = OP_C3X;
1447
 
1448
  if ( IS_CPU_TIC4X(tic4x_cpu) )
1449
    tic4x_oplevel |= OP_C4X;
1450
 
1451
  if ( (   tic4x_cpu == 31 && tic4x_revision >= 6)
1452
       || (tic4x_cpu == 32 && tic4x_revision >= 2)
1453
       || (tic4x_cpu == 33)
1454
       || tic4x_enhanced )
1455
    tic4x_oplevel |= OP_ENH;
1456
 
1457
  if ( (   tic4x_cpu == 30 && tic4x_revision >= 7)
1458
       || (tic4x_cpu == 31 && tic4x_revision >= 5)
1459
       || (tic4x_cpu == 32)
1460
       || tic4x_lowpower )
1461
    tic4x_oplevel |= OP_LPWR;
1462
 
1463
  if ( (   tic4x_cpu == 30 && tic4x_revision >= 7)
1464
       || (tic4x_cpu == 31 && tic4x_revision >= 5)
1465
       || (tic4x_cpu == 32)
1466
       || (tic4x_cpu == 33)
1467
       || (tic4x_cpu == 40 && tic4x_revision >= 5)
1468
       || (tic4x_cpu == 44)
1469
       || tic4x_idle2 )
1470
    tic4x_oplevel |= OP_IDLE2;
1471
 
1472
  /* Create hash table for mnemonics.  */
1473
  tic4x_op_hash = hash_new ();
1474
 
1475
  /* Create hash table for asg pseudo.  */
1476
  tic4x_asg_hash = hash_new ();
1477
 
1478
  /* Add mnemonics to hash table, expanding conditional mnemonics on fly.  */
1479
  for (i = 0; i < tic4x_num_insts; i++)
1480
    ok &= tic4x_inst_add (tic4x_insts + i);
1481
 
1482
  /* Create dummy inst to avoid errors accessing end of table.  */
1483
  tic4x_inst_make ("", 0, "");
1484
 
1485
  if (!ok)
1486
    as_fatal ("Broken assembler.  No assembly attempted.");
1487
 
1488
  /* Add registers to symbol table.  */
1489
  tic4x_init_regtable ();
1490
 
1491
  /* Add predefined symbols to symbol table.  */
1492
  tic4x_init_symbols ();
1493
}
1494
 
1495
void
1496
tic4x_end ()
1497
{
1498
  bfd_set_arch_mach (stdoutput, bfd_arch_tic4x,
1499
                     IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x);
1500
}
1501
 
1502
static int
1503
tic4x_indirect_parse (operand, indirect)
1504
     tic4x_operand_t *operand;
1505
     const tic4x_indirect_t *indirect;
1506
{
1507
  char *n = indirect->name;
1508
  char *s = input_line_pointer;
1509
  char *b;
1510
  symbolS *symbolP;
1511
  char name[32];
1512
 
1513
  operand->disp = 0;
1514
  for (; *n; n++)
1515
    {
1516
      switch (*n)
1517
        {
1518
        case 'a':               /* Need to match aux register.  */
1519
          b = name;
1520
#ifdef TIC4X_ALT_SYNTAX
1521
          if (*s == '%')
1522
            s++;
1523
#endif
1524
          while (ISALNUM (*s))
1525
            *b++ = *s++;
1526
          *b++ = '\0';
1527
          if (!(symbolP = symbol_find (name)))
1528
            return 0;
1529
 
1530
          if (S_GET_SEGMENT (symbolP) != reg_section)
1531
            return 0;
1532
 
1533
          operand->aregno = S_GET_VALUE (symbolP);
1534
          if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7)
1535
            break;
1536
 
1537
          as_bad ("Auxiliary register AR0--AR7 required for indirect");
1538
          return -1;
1539
 
1540
        case 'd':               /* Need to match constant for disp.  */
1541
#ifdef TIC4X_ALT_SYNTAX
1542
          if (*s == '%')        /* expr() will die if we don't skip this.  */
1543
            s++;
1544
#endif
1545
          s = tic4x_expression (s, &operand->expr);
1546
          if (operand->expr.X_op != O_constant)
1547
            return 0;
1548
          operand->disp = operand->expr.X_add_number;
1549
          if (operand->disp < 0 || operand->disp > 255)
1550
            {
1551
              as_bad ("Bad displacement %d (require 0--255)\n",
1552
                      operand->disp);
1553
              return -1;
1554
            }
1555
          break;
1556
 
1557
        case 'y':               /* Need to match IR0.  */
1558
        case 'z':               /* Need to match IR1.  */
1559
#ifdef TIC4X_ALT_SYNTAX
1560
          if (*s == '%')
1561
            s++;
1562
#endif
1563
          s = tic4x_expression (s, &operand->expr);
1564
          if (operand->expr.X_op != O_register)
1565
            return 0;
1566
          if (operand->expr.X_add_number != REG_IR0
1567
              && operand->expr.X_add_number != REG_IR1)
1568
            {
1569
              as_bad ("Index register IR0,IR1 required for displacement");
1570
              return -1;
1571
            }
1572
 
1573
          if (*n == 'y' && operand->expr.X_add_number == REG_IR0)
1574
            break;
1575
          if (*n == 'z' && operand->expr.X_add_number == REG_IR1)
1576
            break;
1577
          return 0;
1578
 
1579
        case '(':
1580
          if (*s != '(')        /* No displacement, assume to be 1.  */
1581
            {
1582
              operand->disp = 1;
1583
              while (*n != ')')
1584
                n++;
1585
            }
1586
          else
1587
            s++;
1588
          break;
1589
 
1590
        default:
1591
          if (TOLOWER (*s) != *n)
1592
            return 0;
1593
          s++;
1594
        }
1595
    }
1596
  if (*s != ' ' && *s != ',' && *s != '\0')
1597
    return 0;
1598
  input_line_pointer = s;
1599
  return 1;
1600
}
1601
 
1602
static char *
1603
tic4x_operand_parse (s, operand)
1604
     char *s;
1605
     tic4x_operand_t *operand;
1606
{
1607
  unsigned int i;
1608
  char c;
1609
  int ret;
1610
  expressionS *exp = &operand->expr;
1611
  char *save = input_line_pointer;
1612
  char *str;
1613
  char *new;
1614
  struct hash_entry *entry = NULL;
1615
 
1616
  input_line_pointer = s;
1617
  SKIP_WHITESPACE ();
1618
 
1619
  str = input_line_pointer;
1620
  c = get_symbol_end ();        /* Get terminator.  */
1621
  new = input_line_pointer;
1622
  if (strlen (str) && (entry = hash_find (tic4x_asg_hash, str)) != NULL)
1623
    {
1624
      *input_line_pointer = c;
1625
      input_line_pointer = (char *) entry;
1626
    }
1627
  else
1628
    {
1629
      *input_line_pointer = c;
1630
      input_line_pointer = str;
1631
    }
1632
 
1633
  operand->mode = M_UNKNOWN;
1634
  switch (*input_line_pointer)
1635
    {
1636
#ifdef TIC4X_ALT_SYNTAX
1637
    case '%':
1638
      input_line_pointer = tic4x_expression (++input_line_pointer, exp);
1639
      if (exp->X_op != O_register)
1640
        as_bad ("Expecting a register name");
1641
      operand->mode = M_REGISTER;
1642
      break;
1643
 
1644
    case '^':
1645
      /* Denotes high 16 bits.  */
1646
      input_line_pointer = tic4x_expression (++input_line_pointer, exp);
1647
      if (exp->X_op == O_constant)
1648
        operand->mode = M_IMMED;
1649
      else if (exp->X_op == O_big)
1650
        {
1651
          if (exp->X_add_number)
1652
            as_bad ("Number too large");        /* bignum required */
1653
          else
1654
            {
1655
              tic4x_gen_to_words (generic_floating_point_number,
1656
                                operand->fwords, S_PRECISION);
1657
              operand->mode = M_IMMED_F;
1658
            }
1659
        }
1660
      /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0  */
1661
      /* WARNING : The TI C40 assembler cannot do this.  */
1662
      else if (exp->X_op == O_symbol)
1663
        {
1664
          operand->mode = M_HI;
1665
          break;
1666
        }
1667
 
1668
    case '#':
1669
      input_line_pointer = tic4x_expression (++input_line_pointer, exp);
1670
      if (exp->X_op == O_constant)
1671
        operand->mode = M_IMMED;
1672
      else if (exp->X_op == O_big)
1673
        {
1674
          if (exp->X_add_number > 0)
1675
            as_bad ("Number too large");        /* bignum required.  */
1676
          else
1677
            {
1678
              tic4x_gen_to_words (generic_floating_point_number,
1679
                                operand->fwords, S_PRECISION);
1680
              operand->mode = M_IMMED_F;
1681
            }
1682
        }
1683
      /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0  */
1684
      /* WARNING : The TI C40 assembler cannot do this.  */
1685
      else if (exp->X_op == O_symbol)
1686
        {
1687
          operand->mode = M_IMMED;
1688
          break;
1689
        }
1690
 
1691
      else
1692
        as_bad ("Expecting a constant value");
1693
      break;
1694
    case '\\':
1695
#endif
1696
    case '@':
1697
      input_line_pointer = tic4x_expression (++input_line_pointer, exp);
1698
      if (exp->X_op != O_constant && exp->X_op != O_symbol)
1699
        as_bad ("Bad direct addressing construct %s", s);
1700
      if (exp->X_op == O_constant)
1701
        {
1702
          if (exp->X_add_number < 0)
1703
            as_bad ("Direct value of %ld is not suitable",
1704
                    (long) exp->X_add_number);
1705
        }
1706
      operand->mode = M_DIRECT;
1707
      break;
1708
 
1709
    case '*':
1710
      ret = -1;
1711
      for (i = 0; i < tic4x_num_indirects; i++)
1712
        if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i])))
1713
          break;
1714
      if (ret < 0)
1715
        break;
1716
      if (i < tic4x_num_indirects)
1717
        {
1718
          operand->mode = M_INDIRECT;
1719
          /* Indirect addressing mode number.  */
1720
          operand->expr.X_add_number = tic4x_indirects[i].modn;
1721
          /* Convert *+ARn(0) to *ARn etc.  Maybe we should
1722
             squeal about silly ones?  */
1723
          if (operand->expr.X_add_number < 0x08 && !operand->disp)
1724
            operand->expr.X_add_number = 0x18;
1725
        }
1726
      else
1727
        as_bad ("Unknown indirect addressing mode");
1728
      break;
1729
 
1730
    default:
1731
      operand->mode = M_IMMED;  /* Assume immediate.  */
1732
      str = input_line_pointer;
1733
      input_line_pointer = tic4x_expression (input_line_pointer, exp);
1734
      if (exp->X_op == O_register)
1735
        {
1736
          know (exp->X_add_symbol == 0);
1737
          know (exp->X_op_symbol == 0);
1738
          operand->mode = M_REGISTER;
1739
          break;
1740
        }
1741
      else if (exp->X_op == O_big)
1742
        {
1743
          if (exp->X_add_number > 0)
1744
            as_bad ("Number too large");        /* bignum required.  */
1745
          else
1746
            {
1747
              tic4x_gen_to_words (generic_floating_point_number,
1748
                                operand->fwords, S_PRECISION);
1749
              operand->mode = M_IMMED_F;
1750
            }
1751
          break;
1752
        }
1753
#ifdef TIC4X_ALT_SYNTAX
1754
      /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0.  */
1755
      else if (exp->X_op == O_symbol)
1756
        {
1757
          operand->mode = M_DIRECT;
1758
          break;
1759
        }
1760
#endif
1761
    }
1762
  if (entry == NULL)
1763
    new = input_line_pointer;
1764
  input_line_pointer = save;
1765
  return new;
1766
}
1767
 
1768
static int
1769
tic4x_operands_match (inst, insn, check)
1770
     tic4x_inst_t *inst;
1771
     tic4x_insn_t *insn;
1772
     int check;
1773
{
1774
  const char *args = inst->args;
1775
  unsigned long opcode = inst->opcode;
1776
  int num_operands = insn->num_operands;
1777
  tic4x_operand_t *operand = insn->operands;
1778
  expressionS *exp = &operand->expr;
1779
  int ret = 1;
1780
  int reg;
1781
 
1782
  /* Build the opcode, checking as we go to make sure that the
1783
     operands match.
1784
 
1785
     If an operand matches, we modify insn or opcode appropriately,
1786
     and do a "continue".  If an operand fails to match, we "break".  */
1787
 
1788
  insn->nchars = 4;             /* Instructions always 4 bytes.  */
1789
  insn->reloc = NO_RELOC;
1790
  insn->pcrel = 0;
1791
 
1792
  if (*args == '\0')
1793
    {
1794
      insn->opcode = opcode;
1795
      return num_operands == 0;
1796
    }
1797
 
1798
  for (;; ++args)
1799
    {
1800
      switch (*args)
1801
        {
1802
 
1803
        case '\0':              /* End of args.  */
1804
          if (num_operands == 1)
1805
            {
1806
              insn->opcode = opcode;
1807
              return ret;
1808
            }
1809
          break;                /* Too many operands.  */
1810
 
1811
        case '#':               /* This is only used for ldp.  */
1812
          if (operand->mode != M_DIRECT && operand->mode != M_IMMED)
1813
            break;
1814
          /* While this looks like a direct addressing mode, we actually
1815
             use an immediate mode form of ldiu or ldpk instruction.  */
1816
          if (exp->X_op == O_constant)
1817
            {
1818
              if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 )
1819
                  || ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) )
1820
                {
1821
                  INSERTS (opcode, exp->X_add_number, 15, 0);
1822
                  continue;
1823
                }
1824
              else
1825
                {
1826
                  if (!check)
1827
                    as_bad ("Immediate value of %ld is too large for ldf",
1828
                            (long) exp->X_add_number);
1829
                  ret = -1;
1830
                  continue;
1831
                }
1832
            }
1833
          else if (exp->X_op == O_symbol)
1834
            {
1835
              insn->reloc = BFD_RELOC_HI16;
1836
              insn->exp = *exp;
1837
              continue;
1838
            }
1839
          break;                /* Not direct (dp) addressing.  */
1840
 
1841
        case '@':               /* direct.  */
1842
          if (operand->mode != M_DIRECT)
1843
            break;
1844
          if (exp->X_op == O_constant)
1845
            {
1846
              /* Store only the 16 LSBs of the number.  */
1847
              INSERTS (opcode, exp->X_add_number, 15, 0);
1848
              continue;
1849
            }
1850
          else if (exp->X_op == O_symbol)
1851
            {
1852
              insn->reloc = BFD_RELOC_LO16;
1853
              insn->exp = *exp;
1854
              continue;
1855
            }
1856
          break;                /* Not direct addressing.  */
1857
 
1858
        case 'A':
1859
          if (operand->mode != M_REGISTER)
1860
            break;
1861
          reg = exp->X_add_number;
1862
          if (reg >= REG_AR0 && reg <= REG_AR7)
1863
            INSERTU (opcode, reg - REG_AR0, 24, 22);
1864
          else
1865
            {
1866
              if (!check)
1867
                as_bad ("Destination register must be ARn");
1868
              ret = -1;
1869
            }
1870
          continue;
1871
 
1872
        case 'B':               /* Unsigned integer immediate.  */
1873
          /* Allow br label or br @label.  */
1874
          if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
1875
            break;
1876
          if (exp->X_op == O_constant)
1877
            {
1878
              if (exp->X_add_number < (1 << 24))
1879
                {
1880
                  INSERTU (opcode, exp->X_add_number, 23, 0);
1881
                  continue;
1882
                }
1883
              else
1884
                {
1885
                  if (!check)
1886
                    as_bad ("Immediate value of %ld is too large",
1887
                            (long) exp->X_add_number);
1888
                  ret = -1;
1889
                  continue;
1890
                }
1891
            }
1892
          if (IS_CPU_TIC4X (tic4x_cpu))
1893
            {
1894
              insn->reloc = BFD_RELOC_24_PCREL;
1895
              insn->pcrel = 1;
1896
            }
1897
          else
1898
            {
1899
              insn->reloc = BFD_RELOC_24;
1900
              insn->pcrel = 0;
1901
            }
1902
          insn->exp = *exp;
1903
          continue;
1904
 
1905
        case 'C':
1906
          if (!IS_CPU_TIC4X (tic4x_cpu))
1907
            break;
1908
          if (operand->mode != M_INDIRECT)
1909
            break;
1910
          /* Require either *+ARn(disp) or *ARn.  */
1911
          if (operand->expr.X_add_number != 0
1912
              && operand->expr.X_add_number != 0x18)
1913
            {
1914
              if (!check)
1915
                as_bad ("Invalid indirect addressing mode");
1916
              ret = -1;
1917
              continue;
1918
            }
1919
          INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
1920
          INSERTU (opcode, operand->disp, 7, 3);
1921
          continue;
1922
 
1923
        case 'E':
1924
          if (!(operand->mode == M_REGISTER))
1925
            break;
1926
          INSERTU (opcode, exp->X_add_number, 7, 0);
1927
          continue;
1928
 
1929
        case 'e':
1930
          if (!(operand->mode == M_REGISTER))
1931
            break;
1932
          reg = exp->X_add_number;
1933
          if ( (reg >= REG_R0 && reg <= REG_R7)
1934
               || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
1935
            INSERTU (opcode, reg, 7, 0);
1936
          else
1937
            {
1938
              if (!check)
1939
                as_bad ("Register must be Rn");
1940
              ret = -1;
1941
            }
1942
          continue;
1943
 
1944
        case 'F':
1945
          if (operand->mode != M_IMMED_F
1946
              && !(operand->mode == M_IMMED && exp->X_op == O_constant))
1947
            break;
1948
 
1949
          if (operand->mode != M_IMMED_F)
1950
            {
1951
              /* OK, we 've got something like cmpf 0, r0
1952
                 Why can't they stick in a bloody decimal point ?!  */
1953
              char string[16];
1954
 
1955
              /* Create floating point number string.  */
1956
              sprintf (string, "%d.0", (int) exp->X_add_number);
1957
              tic4x_atof (string, 's', operand->fwords);
1958
            }
1959
 
1960
          INSERTU (opcode, operand->fwords[0], 15, 0);
1961
          continue;
1962
 
1963
        case 'G':
1964
          if (operand->mode != M_REGISTER)
1965
            break;
1966
          INSERTU (opcode, exp->X_add_number, 15, 8);
1967
          continue;
1968
 
1969
        case 'g':
1970
          if (operand->mode != M_REGISTER)
1971
            break;
1972
          reg = exp->X_add_number;
1973
          if ( (reg >= REG_R0 && reg <= REG_R7)
1974
               || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
1975
            INSERTU (opcode, reg, 15, 8);
1976
          else
1977
            {
1978
              if (!check)
1979
                as_bad ("Register must be Rn");
1980
              ret = -1;
1981
            }
1982
          continue;
1983
 
1984
        case 'H':
1985
          if (operand->mode != M_REGISTER)
1986
            break;
1987
          reg = exp->X_add_number;
1988
          if (reg >= REG_R0 && reg <= REG_R7)
1989
            INSERTU (opcode, reg - REG_R0, 18, 16);
1990
          else
1991
            {
1992
              if (!check)
1993
                as_bad ("Register must be R0--R7");
1994
              ret = -1;
1995
            }
1996
          continue;
1997
 
1998
        case 'i':
1999
          if ( operand->mode == M_REGISTER
2000
               && tic4x_oplevel & OP_ENH )
2001
            {
2002
              reg = exp->X_add_number;
2003
              INSERTU (opcode, reg, 4, 0);
2004
              INSERTU (opcode, 7, 7, 5);
2005
              continue;
2006
            }
2007
          /* Fallthrough */
2008
 
2009
        case 'I':
2010
          if (operand->mode != M_INDIRECT)
2011
            break;
2012
          if (operand->disp != 0 && operand->disp != 1)
2013
            {
2014
              if (IS_CPU_TIC4X (tic4x_cpu))
2015
                break;
2016
              if (!check)
2017
                as_bad ("Invalid indirect addressing mode displacement %d",
2018
                        operand->disp);
2019
              ret = -1;
2020
              continue;
2021
            }
2022
          INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
2023
          INSERTU (opcode, operand->expr.X_add_number, 7, 3);
2024
          continue;
2025
 
2026
        case 'j':
2027
          if ( operand->mode == M_REGISTER
2028
               && tic4x_oplevel & OP_ENH )
2029
            {
2030
              reg = exp->X_add_number;
2031
              INSERTU (opcode, reg, 12, 8);
2032
              INSERTU (opcode, 7, 15, 13);
2033
              continue;
2034
            }
2035
          /* Fallthrough */
2036
 
2037
        case 'J':
2038
          if (operand->mode != M_INDIRECT)
2039
            break;
2040
          if (operand->disp != 0 && operand->disp != 1)
2041
            {
2042
              if (IS_CPU_TIC4X (tic4x_cpu))
2043
                break;
2044
              if (!check)
2045
                as_bad ("Invalid indirect addressing mode displacement %d",
2046
                        operand->disp);
2047
              ret = -1;
2048
              continue;
2049
            }
2050
          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2051
          INSERTU (opcode, operand->expr.X_add_number, 15, 11);
2052
          continue;
2053
 
2054
        case 'K':
2055
          if (operand->mode != M_REGISTER)
2056
            break;
2057
          reg = exp->X_add_number;
2058
          if (reg >= REG_R0 && reg <= REG_R7)
2059
            INSERTU (opcode, reg - REG_R0, 21, 19);
2060
          else
2061
            {
2062
              if (!check)
2063
                as_bad ("Register must be R0--R7");
2064
              ret = -1;
2065
            }
2066
          continue;
2067
 
2068
        case 'L':
2069
          if (operand->mode != M_REGISTER)
2070
            break;
2071
          reg = exp->X_add_number;
2072
          if (reg >= REG_R0 && reg <= REG_R7)
2073
            INSERTU (opcode, reg - REG_R0, 24, 22);
2074
          else
2075
            {
2076
              if (!check)
2077
                as_bad ("Register must be R0--R7");
2078
              ret = -1;
2079
            }
2080
          continue;
2081
 
2082
        case 'M':
2083
          if (operand->mode != M_REGISTER)
2084
            break;
2085
          reg = exp->X_add_number;
2086
          if (reg == REG_R2 || reg == REG_R3)
2087
            INSERTU (opcode, reg - REG_R2, 22, 22);
2088
          else
2089
            {
2090
              if (!check)
2091
                as_bad ("Destination register must be R2 or R3");
2092
              ret = -1;
2093
            }
2094
          continue;
2095
 
2096
        case 'N':
2097
          if (operand->mode != M_REGISTER)
2098
            break;
2099
          reg = exp->X_add_number;
2100
          if (reg == REG_R0 || reg == REG_R1)
2101
            INSERTU (opcode, reg - REG_R0, 23, 23);
2102
          else
2103
            {
2104
              if (!check)
2105
                as_bad ("Destination register must be R0 or R1");
2106
              ret = -1;
2107
            }
2108
          continue;
2109
 
2110
        case 'O':
2111
          if (!IS_CPU_TIC4X (tic4x_cpu))
2112
            break;
2113
          if (operand->mode != M_INDIRECT)
2114
            break;
2115
          /* Require either *+ARn(disp) or *ARn.  */
2116
          if (operand->expr.X_add_number != 0
2117
              && operand->expr.X_add_number != 0x18)
2118
            {
2119
              if (!check)
2120
                as_bad ("Invalid indirect addressing mode");
2121
              ret = -1;
2122
              continue;
2123
            }
2124
          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2125
          INSERTU (opcode, operand->disp, 15, 11);
2126
          continue;
2127
 
2128
        case 'P':               /* PC relative displacement.  */
2129
          /* Allow br label or br @label.  */
2130
          if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
2131
            break;
2132
          if (exp->X_op == O_constant)
2133
            {
2134
              if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767)
2135
                {
2136
                  INSERTS (opcode, exp->X_add_number, 15, 0);
2137
                  continue;
2138
                }
2139
              else
2140
                {
2141
                  if (!check)
2142
                    as_bad ("Displacement value of %ld is too large",
2143
                            (long) exp->X_add_number);
2144
                  ret = -1;
2145
                  continue;
2146
                }
2147
            }
2148
          insn->reloc = BFD_RELOC_16_PCREL;
2149
          insn->pcrel = 1;
2150
          insn->exp = *exp;
2151
          continue;
2152
 
2153
        case 'Q':
2154
          if (operand->mode != M_REGISTER)
2155
            break;
2156
          reg = exp->X_add_number;
2157
          INSERTU (opcode, reg, 15, 0);
2158
          continue;
2159
 
2160
        case 'q':
2161
          if (operand->mode != M_REGISTER)
2162
            break;
2163
          reg = exp->X_add_number;
2164
          if ( (reg >= REG_R0 && reg <= REG_R7)
2165
               || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
2166
            INSERTU (opcode, reg, 15, 0);
2167
          else
2168
            {
2169
              if (!check)
2170
                as_bad ("Register must be Rn");
2171
              ret = -1;
2172
            }
2173
          continue;
2174
 
2175
        case 'R':
2176
          if (operand->mode != M_REGISTER)
2177
            break;
2178
          reg = exp->X_add_number;
2179
          INSERTU (opcode, reg, 20, 16);
2180
          continue;
2181
 
2182
        case 'r':
2183
          if (operand->mode != M_REGISTER)
2184
            break;
2185
          reg = exp->X_add_number;
2186
          if ( (reg >= REG_R0 && reg <= REG_R7)
2187
               || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
2188
            INSERTU (opcode, reg, 20, 16);
2189
          else
2190
            {
2191
              if (!check)
2192
                as_bad ("Register must be Rn");
2193
              ret = -1;
2194
            }
2195
          continue;
2196
 
2197
        case 'S':               /* Short immediate int.  */
2198
          if (operand->mode != M_IMMED && operand->mode != M_HI)
2199
            break;
2200
          if (exp->X_op == O_big)
2201
            {
2202
              if (!check)
2203
                as_bad ("Floating point number not valid in expression");
2204
              ret = -1;
2205
              continue;
2206
            }
2207
          if (exp->X_op == O_constant)
2208
            {
2209
              if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535)
2210
                {
2211
                  INSERTS (opcode, exp->X_add_number, 15, 0);
2212
                  continue;
2213
                }
2214
              else
2215
                {
2216
                  if (!check)
2217
                    as_bad ("Signed immediate value %ld too large",
2218
                            (long) exp->X_add_number);
2219
                  ret = -1;
2220
                  continue;
2221
                }
2222
            }
2223
          else if (exp->X_op == O_symbol)
2224
            {
2225
              if (operand->mode == M_HI)
2226
                {
2227
                  insn->reloc = BFD_RELOC_HI16;
2228
                }
2229
              else
2230
                {
2231
                  insn->reloc = BFD_RELOC_LO16;
2232
                }
2233
              insn->exp = *exp;
2234
              continue;
2235
            }
2236
          /* Handle cases like ldi foo - $, ar0  where foo
2237
             is a forward reference.  Perhaps we should check
2238
             for X_op == O_symbol and disallow things like
2239
             ldi foo, ar0.  */
2240
          insn->reloc = BFD_RELOC_16;
2241
          insn->exp = *exp;
2242
          continue;
2243
 
2244
        case 'T':               /* 5-bit immediate value for tic4x stik.  */
2245
          if (!IS_CPU_TIC4X (tic4x_cpu))
2246
            break;
2247
          if (operand->mode != M_IMMED)
2248
            break;
2249
          if (exp->X_op == O_constant)
2250
            {
2251
              if (exp->X_add_number < 16 && exp->X_add_number >= -16)
2252
                {
2253
                  INSERTS (opcode, exp->X_add_number, 20, 16);
2254
                  continue;
2255
                }
2256
              else
2257
                {
2258
                  if (!check)
2259
                    as_bad ("Immediate value of %ld is too large",
2260
                            (long) exp->X_add_number);
2261
                  ret = -1;
2262
                  continue;
2263
                }
2264
            }
2265
          break;                /* No relocations allowed.  */
2266
 
2267
        case 'U':               /* Unsigned integer immediate.  */
2268
          if (operand->mode != M_IMMED && operand->mode != M_HI)
2269
            break;
2270
          if (exp->X_op == O_constant)
2271
            {
2272
              if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0)
2273
                {
2274
                  INSERTU (opcode, exp->X_add_number, 15, 0);
2275
                  continue;
2276
                }
2277
              else
2278
                {
2279
                  if (!check)
2280
                    as_bad ("Unsigned immediate value %ld too large",
2281
                            (long) exp->X_add_number);
2282
                  ret = -1;
2283
                  continue;
2284
                }
2285
            }
2286
          else if (exp->X_op == O_symbol)
2287
            {
2288
              if (operand->mode == M_HI)
2289
                insn->reloc = BFD_RELOC_HI16;
2290
              else
2291
                insn->reloc = BFD_RELOC_LO16;
2292
 
2293
              insn->exp = *exp;
2294
              continue;
2295
            }
2296
          insn->reloc = BFD_RELOC_16;
2297
          insn->exp = *exp;
2298
          continue;
2299
 
2300
        case 'V':               /* Trap numbers (immediate field).  */
2301
          if (operand->mode != M_IMMED)
2302
            break;
2303
          if (exp->X_op == O_constant)
2304
            {
2305
              if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu))
2306
                {
2307
                  INSERTU (opcode, exp->X_add_number, 8, 0);
2308
                  continue;
2309
                }
2310
              else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu))
2311
                {
2312
                  INSERTU (opcode, exp->X_add_number | 0x20, 4, 0);
2313
                  continue;
2314
                }
2315
              else
2316
                {
2317
                  if (!check)
2318
                    as_bad ("Immediate value of %ld is too large",
2319
                            (long) exp->X_add_number);
2320
                  ret = -1;
2321
                  continue;
2322
                }
2323
            }
2324
          break;                /* No relocations allowed.  */
2325
 
2326
        case 'W':               /* Short immediate int (0--7).  */
2327
          if (!IS_CPU_TIC4X (tic4x_cpu))
2328
            break;
2329
          if (operand->mode != M_IMMED)
2330
            break;
2331
          if (exp->X_op == O_big)
2332
            {
2333
              if (!check)
2334
                as_bad ("Floating point number not valid in expression");
2335
              ret = -1;
2336
              continue;
2337
            }
2338
          if (exp->X_op == O_constant)
2339
            {
2340
              if (exp->X_add_number >= -256 && exp->X_add_number <= 127)
2341
                {
2342
                  INSERTS (opcode, exp->X_add_number, 7, 0);
2343
                  continue;
2344
                }
2345
              else
2346
                {
2347
                  if (!check)
2348
                    as_bad ("Immediate value %ld too large",
2349
                            (long) exp->X_add_number);
2350
                  ret = -1;
2351
                  continue;
2352
                }
2353
            }
2354
          insn->reloc = BFD_RELOC_16;
2355
          insn->exp = *exp;
2356
          continue;
2357
 
2358
        case 'X':               /* Expansion register for tic4x.  */
2359
          if (operand->mode != M_REGISTER)
2360
            break;
2361
          reg = exp->X_add_number;
2362
          if (reg >= REG_IVTP && reg <= REG_TVTP)
2363
            INSERTU (opcode, reg - REG_IVTP, 4, 0);
2364
          else
2365
            {
2366
              if (!check)
2367
                as_bad ("Register must be ivtp or tvtp");
2368
              ret = -1;
2369
            }
2370
          continue;
2371
 
2372
        case 'Y':               /* Address register for tic4x lda.  */
2373
          if (operand->mode != M_REGISTER)
2374
            break;
2375
          reg = exp->X_add_number;
2376
          if (reg >= REG_AR0 && reg <= REG_SP)
2377
            INSERTU (opcode, reg, 20, 16);
2378
          else
2379
            {
2380
              if (!check)
2381
                as_bad ("Register must be address register");
2382
              ret = -1;
2383
            }
2384
          continue;
2385
 
2386
        case 'Z':               /* Expansion register for tic4x.  */
2387
          if (operand->mode != M_REGISTER)
2388
            break;
2389
          reg = exp->X_add_number;
2390
          if (reg >= REG_IVTP && reg <= REG_TVTP)
2391
            INSERTU (opcode, reg - REG_IVTP, 20, 16);
2392
          else
2393
            {
2394
              if (!check)
2395
                as_bad ("Register must be ivtp or tvtp");
2396
              ret = -1;
2397
            }
2398
          continue;
2399
 
2400
        case '*':
2401
          if (operand->mode != M_INDIRECT)
2402
            break;
2403
          INSERTS (opcode, operand->disp, 7, 0);
2404
          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
2405
          INSERTU (opcode, operand->expr.X_add_number, 15, 11);
2406
          continue;
2407
 
2408
        case '|':               /* treat as `,' if have ldi_ldi form.  */
2409
          if (insn->parallel)
2410
            {
2411
              if (--num_operands < 0)
2412
                break;          /* Too few operands.  */
2413
              operand++;
2414
              if (operand->mode != M_PARALLEL)
2415
                break;
2416
            }
2417
          /* Fall through.  */
2418
 
2419
        case ',':               /* Another operand.  */
2420
          if (--num_operands < 0)
2421
            break;              /* Too few operands.  */
2422
          operand++;
2423
          exp = &operand->expr;
2424
          continue;
2425
 
2426
        case ';':               /* Another optional operand.  */
2427
          if (num_operands == 1 || operand[1].mode == M_PARALLEL)
2428
            continue;
2429
          if (--num_operands < 0)
2430
            break;              /* Too few operands.  */
2431
          operand++;
2432
          exp = &operand->expr;
2433
          continue;
2434
 
2435
        default:
2436
          BAD_CASE (*args);
2437
        }
2438
      return 0;
2439
    }
2440
}
2441
 
2442
static void
2443
tic4x_insn_check (insn)
2444
     tic4x_insn_t *insn;
2445
{
2446
 
2447
  if (!strcmp(insn->name, "lda"))
2448
    {
2449
      if (insn->num_operands < 2 || insn->num_operands > 2)
2450
        as_fatal ("Illegal internal LDA insn definition");
2451
 
2452
      if ( insn->operands[0].mode == M_REGISTER
2453
           && insn->operands[1].mode == M_REGISTER
2454
           && insn->operands[0].expr.X_add_number == insn->operands[1].expr.X_add_number )
2455
        as_bad ("Source and destination register should not be equal");
2456
    }
2457
  else if( !strcmp(insn->name, "ldi_ldi")
2458
           || !strcmp(insn->name, "ldi1_ldi2")
2459
           || !strcmp(insn->name, "ldi2_ldi1")
2460
           || !strcmp(insn->name, "ldf_ldf")
2461
           || !strcmp(insn->name, "ldf1_ldf2")
2462
           || !strcmp(insn->name, "ldf2_ldf1") )
2463
    {
2464
      if ( insn->num_operands < 4 && insn->num_operands > 5 )
2465
        as_fatal ("Illegal internal %s insn definition", insn->name);
2466
 
2467
      if ( insn->operands[1].mode == M_REGISTER
2468
           && insn->operands[insn->num_operands-1].mode == M_REGISTER
2469
           && insn->operands[1].expr.X_add_number == insn->operands[insn->num_operands-1].expr.X_add_number )
2470
        as_warn ("Equal parallell destination registers, one result will be discarded");
2471
    }
2472
}
2473
 
2474
static void
2475
tic4x_insn_output (insn)
2476
     tic4x_insn_t *insn;
2477
{
2478
  char *dst;
2479
 
2480
  /* Grab another fragment for opcode.  */
2481
  dst = frag_more (insn->nchars);
2482
 
2483
  /* Put out opcode word as a series of bytes in little endian order.  */
2484
  md_number_to_chars (dst, insn->opcode, insn->nchars);
2485
 
2486
  /* Put out the symbol-dependent stuff.  */
2487
  if (insn->reloc != NO_RELOC)
2488
    {
2489
      /* Where is the offset into the fragment for this instruction.  */
2490
      fix_new_exp (frag_now,
2491
                   dst - frag_now->fr_literal,  /* where */
2492
                   insn->nchars,        /* size */
2493
                   &insn->exp,
2494
                   insn->pcrel,
2495
                   insn->reloc);
2496
    }
2497
}
2498
 
2499
/* Parse the operands.  */
2500
int
2501
tic4x_operands_parse (s, operands, num_operands)
2502
     char *s;
2503
     tic4x_operand_t *operands;
2504
     int num_operands;
2505
{
2506
  if (!*s)
2507
    return num_operands;
2508
 
2509
  do
2510
    s = tic4x_operand_parse (s, &operands[num_operands++]);
2511
  while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ',');
2512
 
2513
  if (num_operands > TIC4X_OPERANDS_MAX)
2514
    {
2515
      as_bad ("Too many operands scanned");
2516
      return -1;
2517
    }
2518
  return num_operands;
2519
}
2520
 
2521
/* Assemble a single instruction.  Its label has already been handled
2522
   by the generic front end.  We just parse mnemonic and operands, and
2523
   produce the bytes of data and relocation.  */
2524
void
2525
md_assemble (str)
2526
     char *str;
2527
{
2528
  int ok = 0;
2529
  char *s;
2530
  int i;
2531
  int parsed = 0;
2532
  tic4x_inst_t *inst;           /* Instruction template.  */
2533
  tic4x_inst_t *first_inst;
2534
 
2535
  /* Scan for parallel operators */
2536
  if (str)
2537
    {
2538
      s = str;
2539
      while (*s && *s != '|')
2540
        s++;
2541
 
2542
      if (*s && s[1]=='|')
2543
        {
2544
          if(insn->parallel)
2545
            {
2546
              as_bad ("Parallel opcode cannot contain more than two instructions");
2547
              insn->parallel = 0;
2548
              insn->in_use = 0;
2549
              return;
2550
            }
2551
 
2552
          /* Lets take care of the first part of the parallel insn */
2553
          *s++ = 0;
2554
          md_assemble(str);
2555
          insn->parallel = 1;
2556
          str = ++s;
2557
          /* .. and let the second run though here */
2558
        }
2559
    }
2560
 
2561
  if (str && insn->parallel)
2562
    {
2563
      /* Find mnemonic (second part of parallel instruction).  */
2564
      s = str;
2565
      /* Skip past instruction mnemonic.  */
2566
      while (*s && *s != ' ')
2567
        s++;
2568
      if (*s)                   /* Null terminate for hash_find.  */
2569
        *s++ = '\0';            /* and skip past null.  */
2570
      strcat (insn->name, "_");
2571
      strncat (insn->name, str, TIC4X_NAME_MAX - strlen (insn->name));
2572
 
2573
      insn->operands[insn->num_operands++].mode = M_PARALLEL;
2574
 
2575
      if ((i = tic4x_operands_parse
2576
           (s, insn->operands, insn->num_operands)) < 0)
2577
        {
2578
          insn->parallel = 0;
2579
          insn->in_use = 0;
2580
          return;
2581
        }
2582
      insn->num_operands = i;
2583
      parsed = 1;
2584
    }
2585
 
2586
  if (insn->in_use)
2587
    {
2588
      if ((insn->inst = (struct tic4x_inst *)
2589
           hash_find (tic4x_op_hash, insn->name)) == NULL)
2590
        {
2591
          as_bad ("Unknown opcode `%s'.", insn->name);
2592
          insn->parallel = 0;
2593
          insn->in_use = 0;
2594
          return;
2595
        }
2596
 
2597
      inst = insn->inst;
2598
      first_inst = NULL;
2599
      do
2600
        {
2601
          ok = tic4x_operands_match (inst, insn, 1);
2602
          if (ok < 0)
2603
            {
2604
              if (!first_inst)
2605
                first_inst = inst;
2606
              ok = 0;
2607
            }
2608
      } while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
2609
 
2610
      if (ok > 0)
2611
        {
2612
          tic4x_insn_check (insn);
2613
          tic4x_insn_output (insn);
2614
        }
2615
      else if (!ok)
2616
        {
2617
          if (first_inst)
2618
            tic4x_operands_match (first_inst, insn, 0);
2619
          as_bad ("Invalid operands for %s", insn->name);
2620
        }
2621
      else
2622
        as_bad ("Invalid instruction %s", insn->name);
2623
    }
2624
 
2625
  if (str && !parsed)
2626
    {
2627
      /* Find mnemonic.  */
2628
      s = str;
2629
      while (*s && *s != ' ')   /* Skip past instruction mnemonic.  */
2630
        s++;
2631
      if (*s)                   /* Null terminate for hash_find.  */
2632
        *s++ = '\0';            /* and skip past null.  */
2633
      strncpy (insn->name, str, TIC4X_NAME_MAX - 3);
2634
 
2635
      if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0)
2636
        {
2637
          insn->inst = NULL;    /* Flag that error occurred.  */
2638
          insn->parallel = 0;
2639
          insn->in_use = 0;
2640
          return;
2641
        }
2642
      insn->num_operands = i;
2643
      insn->in_use = 1;
2644
    }
2645
  else
2646
    insn->in_use = 0;
2647
  insn->parallel = 0;
2648
}
2649
 
2650
void
2651
tic4x_cleanup ()
2652
{
2653
  if (insn->in_use)
2654
    md_assemble (NULL);
2655
}
2656
 
2657
/* Turn a string in input_line_pointer into a floating point constant
2658
   of type type, and store the appropriate bytes in *litP.  The number
2659
   of chars emitted is stored in *sizeP.  An error message is
2660
   returned, or NULL on OK.  */
2661
 
2662
char *
2663
md_atof (int type, char *litP, int *sizeP)
2664
{
2665
  int prec;
2666
  int ieee;
2667
  LITTLENUM_TYPE words[MAX_LITTLENUMS];
2668
  LITTLENUM_TYPE *wordP;
2669
  char *t;
2670
 
2671
  switch (type)
2672
    {
2673
    case 's':           /* .single  */
2674
    case 'S':
2675
      ieee = 0;
2676
      prec = 1;
2677
      break;
2678
 
2679
    case 'd':           /* .double  */
2680
    case 'D':
2681
    case 'f':           /* .float  */
2682
    case 'F':
2683
      ieee = 0;
2684
      prec = 2;         /* 1 32-bit word */
2685
      break;
2686
 
2687
    case 'i':           /* .ieee */
2688
    case 'I':
2689
      prec = 2;
2690
      ieee = 1;
2691
      type = 'f';  /* Rewrite type to be usable by atof_ieee().  */
2692
      break;
2693
 
2694
    case 'e':           /* .ldouble */
2695
    case 'E':
2696
      prec = 4;         /* 2 32-bit words */
2697
      ieee = 0;
2698
      break;
2699
 
2700
    default:
2701
      *sizeP = 0;
2702
      return _("Unrecognized or unsupported floating point constant");
2703
    }
2704
 
2705
  if (ieee)
2706
    t = atof_ieee (input_line_pointer, type, words);
2707
  else
2708
    t = tic4x_atof (input_line_pointer, type, words);
2709
  if (t)
2710
    input_line_pointer = t;
2711
  *sizeP = prec * sizeof (LITTLENUM_TYPE);
2712
 
2713
  /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
2714
     little endian byte order.  */
2715
  /* SES: However it is required to put the words (32-bits) out in the
2716
     correct order, hence we write 2 and 2 littlenums in little endian
2717
     order, while we keep the original order on successive words.  */
2718
  for (wordP = words; wordP<(words+prec) ; wordP+=2)
2719
    {
2720
      if (wordP < (words + prec - 1)) /* Dump wordP[1] (if we have one).  */
2721
        {
2722
          md_number_to_chars (litP, (valueT) (wordP[1]),
2723
                              sizeof (LITTLENUM_TYPE));
2724
          litP += sizeof (LITTLENUM_TYPE);
2725
        }
2726
 
2727
      /* Dump wordP[0] */
2728
      md_number_to_chars (litP, (valueT) (wordP[0]),
2729
                          sizeof (LITTLENUM_TYPE));
2730
      litP += sizeof (LITTLENUM_TYPE);
2731
    }
2732
  return NULL;
2733
}
2734
 
2735
void
2736
md_apply_fix (fixP, value, seg)
2737
     fixS *fixP;
2738
     valueT *value;
2739
     segT seg ATTRIBUTE_UNUSED;
2740
{
2741
  char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2742
  valueT val = *value;
2743
 
2744
  switch (fixP->fx_r_type)
2745
    {
2746
    case BFD_RELOC_HI16:
2747
      val >>= 16;
2748
      break;
2749
 
2750
    case BFD_RELOC_LO16:
2751
      val &= 0xffff;
2752
      break;
2753
    default:
2754
      break;
2755
    }
2756
 
2757
  switch (fixP->fx_r_type)
2758
    {
2759
    case BFD_RELOC_32:
2760
      buf[3] = val >> 24;
2761
    case BFD_RELOC_24:
2762
    case BFD_RELOC_24_PCREL:
2763
      buf[2] = val >> 16;
2764
    case BFD_RELOC_16:
2765
    case BFD_RELOC_16_PCREL:
2766
    case BFD_RELOC_LO16:
2767
    case BFD_RELOC_HI16:
2768
      buf[1] = val >> 8;
2769
      buf[0] = val;
2770
      break;
2771
 
2772
    case NO_RELOC:
2773
    default:
2774
      as_bad ("Bad relocation type: 0x%02x", fixP->fx_r_type);
2775
      break;
2776
    }
2777
 
2778
  if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1;
2779
}
2780
 
2781
/* Should never be called for tic4x.  */
2782
void
2783
md_convert_frag (headers, sec, fragP)
2784
     bfd *headers ATTRIBUTE_UNUSED;
2785
     segT sec ATTRIBUTE_UNUSED;
2786
     fragS *fragP ATTRIBUTE_UNUSED;
2787
{
2788
  as_fatal ("md_convert_frag");
2789
}
2790
 
2791
/* Should never be called for tic4x.  */
2792
void
2793
md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
2794
     char *ptr ATTRIBUTE_UNUSED;
2795
     addressT from_addr ATTRIBUTE_UNUSED;
2796
     addressT to_addr ATTRIBUTE_UNUSED;
2797
     fragS *frag ATTRIBUTE_UNUSED;
2798
     symbolS *to_symbol ATTRIBUTE_UNUSED;
2799
{
2800
  as_fatal ("md_create_short_jmp\n");
2801
}
2802
 
2803
/* Should never be called for tic4x.  */
2804
void
2805
md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
2806
     char *ptr ATTRIBUTE_UNUSED;
2807
     addressT from_addr ATTRIBUTE_UNUSED;
2808
     addressT to_addr ATTRIBUTE_UNUSED;
2809
     fragS *frag ATTRIBUTE_UNUSED;
2810
     symbolS *to_symbol ATTRIBUTE_UNUSED;
2811
{
2812
  as_fatal ("md_create_long_jump\n");
2813
}
2814
 
2815
/* Should never be called for tic4x.  */
2816
int
2817
md_estimate_size_before_relax (fragP, segtype)
2818
     register fragS *fragP ATTRIBUTE_UNUSED;
2819
     segT segtype ATTRIBUTE_UNUSED;
2820
{
2821
  as_fatal ("md_estimate_size_before_relax\n");
2822
  return 0;
2823
}
2824
 
2825
 
2826
int
2827
md_parse_option (c, arg)
2828
     int c;
2829
     char *arg;
2830
{
2831
  switch (c)
2832
    {
2833
    case OPTION_CPU:             /* cpu brand */
2834
      if (TOLOWER (*arg) == 'c')
2835
        arg++;
2836
      tic4x_cpu = atoi (arg);
2837
      if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu))
2838
        as_warn ("Unsupported processor generation %d", tic4x_cpu);
2839
      break;
2840
 
2841
    case OPTION_REV:             /* cpu revision */
2842
      tic4x_revision = atoi (arg);
2843
      break;
2844
 
2845
    case 'b':
2846
      as_warn ("Option -b is depreciated, please use -mbig");
2847
    case OPTION_BIG:             /* big model */
2848
      tic4x_big_model = 1;
2849
      break;
2850
 
2851
    case 'p':
2852
      as_warn ("Option -p is depreciated, please use -mmemparm");
2853
    case OPTION_MEMPARM:         /* push args */
2854
      tic4x_reg_args = 0;
2855
      break;
2856
 
2857
    case 'r':
2858
      as_warn ("Option -r is depreciated, please use -mregparm");
2859
    case OPTION_REGPARM:        /* register args */
2860
      tic4x_reg_args = 1;
2861
      break;
2862
 
2863
    case 's':
2864
      as_warn ("Option -s is depreciated, please use -msmall");
2865
    case OPTION_SMALL:          /* small model */
2866
      tic4x_big_model = 0;
2867
      break;
2868
 
2869
    case OPTION_IDLE2:
2870
      tic4x_idle2 = 1;
2871
      break;
2872
 
2873
    case OPTION_LOWPOWER:
2874
      tic4x_lowpower = 1;
2875
      break;
2876
 
2877
    case OPTION_ENHANCED:
2878
      tic4x_enhanced = 1;
2879
      break;
2880
 
2881
    default:
2882
      return 0;
2883
    }
2884
 
2885
  return 1;
2886
}
2887
 
2888
void
2889
md_show_usage (stream)
2890
     FILE *stream;
2891
{
2892
  fprintf (stream,
2893
      _("\nTIC4X options:\n"
2894
        "  -mcpu=CPU  -mCPU        select architecture variant. CPU can be:\n"
2895
        "                            30 - TMS320C30\n"
2896
        "                            31 - TMS320C31, TMS320LC31\n"
2897
        "                            32 - TMS320C32\n"
2898
        "                            33 - TMS320VC33\n"
2899
        "                            40 - TMS320C40\n"
2900
        "                            44 - TMS320C44\n"
2901
        "  -mrev=REV               set cpu hardware revision (integer numbers).\n"
2902
        "                          Combinations of -mcpu and -mrev will enable/disable\n"
2903
        "                          the appropriate options (-midle2, -mlowpower and\n"
2904
        "                          -menhanced) according to the selected type\n"
2905
        "  -mbig                   select big memory model\n"
2906
        "  -msmall                 select small memory model (default)\n"
2907
        "  -mregparm               select register parameters (default)\n"
2908
        "  -mmemparm               select memory parameters\n"
2909
        "  -midle2                 enable IDLE2 support\n"
2910
        "  -mlowpower              enable LOPOWER and MAXSPEED support\n"
2911
        "  -menhanced              enable enhanced opcode support\n"));
2912
}
2913
 
2914
/* This is called when a line is unrecognized.  This is used to handle
2915
   definitions of TI C3x tools style local labels $n where n is a single
2916
   decimal digit.  */
2917
int
2918
tic4x_unrecognized_line (c)
2919
     int c;
2920
{
2921
  int lab;
2922
  char *s;
2923
 
2924
  if (c != '$' || ! ISDIGIT (input_line_pointer[0]))
2925
    return 0;
2926
 
2927
  s = input_line_pointer;
2928
 
2929
  /* Let's allow multiple digit local labels.  */
2930
  lab = 0;
2931
  while (ISDIGIT (*s))
2932
    {
2933
      lab = lab * 10 + *s - '0';
2934
      s++;
2935
    }
2936
 
2937
  if (dollar_label_defined (lab))
2938
    {
2939
      as_bad ("Label \"$%d\" redefined", lab);
2940
      return 0;
2941
    }
2942
 
2943
  define_dollar_label (lab);
2944
  colon (dollar_label_name (lab, 0));
2945
  input_line_pointer = s + 1;
2946
 
2947
  return 1;
2948
}
2949
 
2950
/* Handle local labels peculiar to us referred to in an expression.  */
2951
symbolS *
2952
md_undefined_symbol (name)
2953
     char *name;
2954
{
2955
  /* Look for local labels of the form $n.  */
2956
  if (name[0] == '$' && ISDIGIT (name[1]))
2957
    {
2958
      symbolS *symbolP;
2959
      char *s = name + 1;
2960
      int lab = 0;
2961
 
2962
      while (ISDIGIT ((unsigned char) *s))
2963
        {
2964
          lab = lab * 10 + *s - '0';
2965
          s++;
2966
        }
2967
      if (dollar_label_defined (lab))
2968
        {
2969
          name = dollar_label_name (lab, 0);
2970
          symbolP = symbol_find (name);
2971
        }
2972
      else
2973
        {
2974
          name = dollar_label_name (lab, 1);
2975
          symbolP = symbol_find_or_make (name);
2976
        }
2977
 
2978
      return symbolP;
2979
    }
2980
  return NULL;
2981
}
2982
 
2983
/* Parse an operand that is machine-specific.  */
2984
void
2985
md_operand (expressionP)
2986
     expressionS *expressionP ATTRIBUTE_UNUSED;
2987
{
2988
}
2989
 
2990
/* Round up a section size to the appropriate boundary---do we need this?  */
2991
valueT
2992
md_section_align (segment, size)
2993
     segT segment ATTRIBUTE_UNUSED;
2994
     valueT size;
2995
{
2996
  return size;                  /* Byte (i.e., 32-bit) alignment is fine?  */
2997
}
2998
 
2999
static int
3000
tic4x_pc_offset (op)
3001
     unsigned int op;
3002
{
3003
  /* Determine the PC offset for a C[34]x instruction.
3004
     This could be simplified using some boolean algebra
3005
     but at the expense of readability.  */
3006
  switch (op >> 24)
3007
    {
3008
    case 0x60:                  /* br */
3009
    case 0x62:                  /* call  (C4x) */
3010
    case 0x64:                  /* rptb  (C4x) */
3011
      return 1;
3012
    case 0x61:                  /* brd */
3013
    case 0x63:                  /* laj */
3014
    case 0x65:                  /* rptbd (C4x) */
3015
      return 3;
3016
    case 0x66:                  /* swi */
3017
    case 0x67:
3018
      return 0;
3019
    default:
3020
      break;
3021
    }
3022
 
3023
  switch ((op & 0xffe00000) >> 20)
3024
    {
3025
    case 0x6a0:         /* bB */
3026
    case 0x720:         /* callB */
3027
    case 0x740:         /* trapB */
3028
      return 1;
3029
 
3030
    case 0x6a2:         /* bBd */
3031
    case 0x6a6:         /* bBat */
3032
    case 0x6aa:         /* bBaf */
3033
    case 0x722:         /* lajB */
3034
    case 0x748:         /* latB */
3035
    case 0x798:         /* rptbd */
3036
      return 3;
3037
 
3038
    default:
3039
      break;
3040
    }
3041
 
3042
  switch ((op & 0xfe200000) >> 20)
3043
    {
3044
    case 0x6e0:         /* dbB */
3045
      return 1;
3046
 
3047
    case 0x6e2:         /* dbBd */
3048
      return 3;
3049
 
3050
    default:
3051
      break;
3052
    }
3053
 
3054
  return 0;
3055
}
3056
 
3057
/* Exactly what point is a PC-relative offset relative TO?
3058
   With the C3x we have the following:
3059
   DBcond,  Bcond   disp + PC + 1 => PC
3060
   DBcondD, BcondD  disp + PC + 3 => PC
3061
 */
3062
long
3063
md_pcrel_from (fixP)
3064
     fixS *fixP;
3065
{
3066
  unsigned char *buf;
3067
  unsigned int op;
3068
 
3069
  buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
3070
  op = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
3071
 
3072
  return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
3073
    tic4x_pc_offset (op);
3074
}
3075
 
3076
/* Fill the alignment area with NOP's on .text, unless fill-data
3077
   was specified. */
3078
int
3079
tic4x_do_align (alignment, fill, len, max)
3080
     int alignment ATTRIBUTE_UNUSED;
3081
     const char *fill ATTRIBUTE_UNUSED;
3082
     int len ATTRIBUTE_UNUSED;
3083
     int max ATTRIBUTE_UNUSED;
3084
{
3085
  unsigned long nop = TIC_NOP_OPCODE;
3086
 
3087
  /* Because we are talking lwords, not bytes, adjust alignment to do words */
3088
  alignment += 2;
3089
 
3090
  if (alignment != 0 && !need_pass_2)
3091
    {
3092
      if (fill == NULL)
3093
        {
3094
          /*if (subseg_text_p (now_seg))*/  /* FIXME: doesn't work for .text for some reason */
3095
          frag_align_pattern( alignment, (const char *)&nop, sizeof(nop), max);
3096
          return 1;
3097
          /*else
3098
            frag_align (alignment, 0, max);*/
3099
        }
3100
      else if (len <= 1)
3101
        frag_align (alignment, *fill, max);
3102
      else
3103
        frag_align_pattern (alignment, fill, len, max);
3104
    }
3105
 
3106
  /* Return 1 to skip the default alignment function */
3107
  return 1;
3108
}
3109
 
3110
/* Look for and remove parallel instruction operator ||.  */
3111
void
3112
tic4x_start_line ()
3113
{
3114
  char *s = input_line_pointer;
3115
 
3116
  SKIP_WHITESPACE ();
3117
 
3118
  /* If parallel instruction prefix found at start of line, skip it.  */
3119
  if (*input_line_pointer == '|' && input_line_pointer[1] == '|')
3120
    {
3121
      if (insn->in_use)
3122
        {
3123
          insn->parallel = 1;
3124
          input_line_pointer ++;
3125
          *input_line_pointer = ' ';
3126
          /* So line counters get bumped.  */
3127
          input_line_pointer[-1] = '\n';
3128
        }
3129
    }
3130
  else
3131
    {
3132
      /* Write out the previous insn here */
3133
      if (insn->in_use)
3134
        md_assemble (NULL);
3135
      input_line_pointer = s;
3136
    }
3137
}
3138
 
3139
arelent *
3140
tc_gen_reloc (seg, fixP)
3141
     asection *seg ATTRIBUTE_UNUSED;
3142
     fixS *fixP;
3143
{
3144
  arelent *reloc;
3145
 
3146
  reloc = (arelent *) xmalloc (sizeof (arelent));
3147
 
3148
  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
3149
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3150
  reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3151
  reloc->address /= OCTETS_PER_BYTE;
3152
  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
3153
  if (reloc->howto == (reloc_howto_type *) NULL)
3154
    {
3155
      as_bad_where (fixP->fx_file, fixP->fx_line,
3156
                    "Reloc %d not supported by object file format",
3157
                    (int) fixP->fx_r_type);
3158
      return NULL;
3159
    }
3160
 
3161
  if (fixP->fx_r_type == BFD_RELOC_HI16)
3162
    reloc->addend = fixP->fx_offset;
3163
  else
3164
    reloc->addend = fixP->fx_addnumber;
3165
 
3166
  return reloc;
3167
}

powered by: WebSVN 2.1.0

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