Back to index

cell-binutils  2.17cvs20070401
tc-tic4x.c
Go to the documentation of this file.
00001 /* tc-tic4x.c -- Assemble for the Texas Instruments TMS320C[34]x.
00002    Copyright (C) 1997,1998, 2002, 2003, 2005, 2006 Free Software Foundation.
00003 
00004    Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
00005 
00006    This file is part of GAS, the GNU Assembler.
00007 
00008    GAS is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2, or (at your option)
00011    any later version.
00012 
00013    GAS is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with GAS; see the file COPYING.  If not, write to
00020    the Free Software Foundation, 51 Franklin Street - Fifth Floor, 
00021    Boston, MA 02110-1301, USA.  */
00022 /*
00023   TODOs:
00024   ------
00025   
00026   o .align cannot handle fill-data-width larger than 0xFF/8-bits. It
00027     should be possible to define a 32-bits pattern.
00028 
00029   o .align fills all section with NOP's when used regardless if has
00030     been used in .text or .data. (However the .align is primarily
00031     intended used in .text sections. If you require something else,
00032     use .align <size>,0x00)
00033 
00034   o .align: Implement a 'bu' insn if the number of nop's exceeds 4
00035     within the align frag. if(fragsize>4words) insert bu fragend+1
00036     first.
00037 
00038   o .usect if has symbol on previous line not implemented
00039 
00040   o .sym, .eos, .stag, .etag, .member not implemented
00041 
00042   o Evaluation of constant floating point expressions (expr.c needs
00043     work!)
00044 
00045   o Support 'abc' constants (that is 0x616263)
00046 */
00047 
00048 #include "safe-ctype.h"
00049 #include "as.h"
00050 #include "opcode/tic4x.h"
00051 #include "subsegs.h"
00052 #include "obstack.h"
00053 
00054 /* OK, we accept a syntax similar to the other well known C30
00055    assembly tools.  With TIC4X_ALT_SYNTAX defined we are more
00056    flexible, allowing a more Unix-like syntax:  `%' in front of
00057    register names, `#' in front of immediate constants, and
00058    not requiring `@' in front of direct addresses.  */
00059 
00060 #define TIC4X_ALT_SYNTAX
00061 
00062 /* Equal to MAX_PRECISION in atof-ieee.c.  */
00063 #define MAX_LITTLENUMS 6    /* (12 bytes) */
00064 
00065 /* Handle of the inst mnemonic hash table.  */
00066 static struct hash_control *tic4x_op_hash = NULL;
00067 
00068 /* Handle asg pseudo.  */
00069 static struct hash_control *tic4x_asg_hash = NULL;
00070 
00071 static unsigned int tic4x_cpu = 0;        /* Default to TMS320C40.  */
00072 static unsigned int tic4x_revision = 0;   /* CPU revision */
00073 static unsigned int tic4x_idle2 = 0;      /* Idle2 support */
00074 static unsigned int tic4x_lowpower = 0;   /* Lowpower support */
00075 static unsigned int tic4x_enhanced = 0;   /* Enhanced opcode support */
00076 static unsigned int tic4x_big_model = 0;  /* Default to small memory model.  */
00077 static unsigned int tic4x_reg_args = 0;   /* Default to args passed on stack.  */
00078 static unsigned long tic4x_oplevel = 0;   /* Opcode level */
00079 
00080 #define OPTION_CPU      'm'
00081 #define OPTION_BIG      (OPTION_MD_BASE + 1)
00082 #define OPTION_SMALL    (OPTION_MD_BASE + 2)
00083 #define OPTION_MEMPARM  (OPTION_MD_BASE + 3)
00084 #define OPTION_REGPARM  (OPTION_MD_BASE + 4)
00085 #define OPTION_IDLE2    (OPTION_MD_BASE + 5)
00086 #define OPTION_LOWPOWER (OPTION_MD_BASE + 6)
00087 #define OPTION_ENHANCED (OPTION_MD_BASE + 7)
00088 #define OPTION_REV      (OPTION_MD_BASE + 8)
00089 
00090 CONST char *md_shortopts = "bm:prs";
00091 struct option md_longopts[] =
00092 {
00093   { "mcpu",   required_argument, NULL, OPTION_CPU },
00094   { "mdsp",   required_argument, NULL, OPTION_CPU },
00095   { "mbig",         no_argument, NULL, OPTION_BIG },
00096   { "msmall",       no_argument, NULL, OPTION_SMALL },
00097   { "mmemparm",     no_argument, NULL, OPTION_MEMPARM },
00098   { "mregparm",     no_argument, NULL, OPTION_REGPARM },
00099   { "midle2",       no_argument, NULL, OPTION_IDLE2 },
00100   { "mlowpower",    no_argument, NULL, OPTION_LOWPOWER },
00101   { "menhanced",    no_argument, NULL, OPTION_ENHANCED },
00102   { "mrev",   required_argument, NULL, OPTION_REV },
00103   { NULL, no_argument, NULL, 0 }
00104 };
00105 
00106 size_t md_longopts_size = sizeof (md_longopts);
00107 
00108 
00109 typedef enum
00110   {
00111     M_UNKNOWN, M_IMMED, M_DIRECT, M_REGISTER, M_INDIRECT,
00112     M_IMMED_F, M_PARALLEL, M_HI
00113   }
00114 tic4x_addr_mode_t;
00115 
00116 typedef struct tic4x_operand
00117   {
00118     tic4x_addr_mode_t mode; /* Addressing mode.  */
00119     expressionS expr;              /* Expression.  */
00120     int disp;               /* Displacement for indirect addressing.  */
00121     int aregno;                    /* Aux. register number.  */
00122     LITTLENUM_TYPE fwords[MAX_LITTLENUMS];       /* Float immed. number.  */
00123   }
00124 tic4x_operand_t;
00125 
00126 typedef struct tic4x_insn
00127   {
00128     char name[TIC4X_NAME_MAX];     /* Mnemonic of instruction.  */
00129     unsigned int in_use;    /* True if in_use.  */
00130     unsigned int parallel;  /* True if parallel instruction.  */
00131     unsigned int nchars;    /* This is always 4 for the C30.  */
00132     unsigned long opcode;   /* Opcode number.  */
00133     expressionS exp;        /* Expression required for relocation.  */
00134     int reloc;                     /* Relocation type required.  */
00135     int pcrel;                     /* True if relocation PC relative.  */
00136     char *pname;            /* Name of instruction in parallel.  */
00137     unsigned int num_operands;     /* Number of operands in total.  */
00138     tic4x_inst_t *inst;            /* Pointer to first template.  */
00139     tic4x_operand_t operands[TIC4X_OPERANDS_MAX];
00140   }
00141 tic4x_insn_t;
00142 
00143 static tic4x_insn_t the_insn;      /* Info about our instruction.  */
00144 static tic4x_insn_t *insn = &the_insn;
00145 
00146 static int tic4x_gen_to_words
00147   PARAMS ((FLONUM_TYPE, LITTLENUM_TYPE *, int ));
00148 static char *tic4x_atof
00149   PARAMS ((char *, char, LITTLENUM_TYPE * ));
00150 static void tic4x_insert_reg
00151   PARAMS ((char *, int ));
00152 static void tic4x_insert_sym
00153   PARAMS ((char *, int ));
00154 static char *tic4x_expression
00155   PARAMS ((char *, expressionS *));
00156 static char *tic4x_expression_abs
00157   PARAMS ((char *, offsetT *));
00158 static void tic4x_emit_char
00159   PARAMS ((char, int));
00160 static void tic4x_seg_alloc
00161   PARAMS ((char *, segT, int, symbolS *));
00162 static void tic4x_asg
00163   PARAMS ((int));
00164 static void tic4x_bss
00165   PARAMS ((int));
00166 static void tic4x_globl
00167   PARAMS ((int));
00168 static void tic4x_cons
00169   PARAMS ((int));
00170 static void tic4x_stringer
00171   PARAMS ((int));
00172 static void tic4x_eval
00173   PARAMS ((int));
00174 static void tic4x_newblock
00175   PARAMS ((int));
00176 static void tic4x_sect
00177   PARAMS ((int));
00178 static void tic4x_set
00179   PARAMS ((int));
00180 static void tic4x_usect
00181   PARAMS ((int));
00182 static void tic4x_version
00183   PARAMS ((int));
00184 static void tic4x_init_regtable
00185   PARAMS ((void));
00186 static void tic4x_init_symbols
00187   PARAMS ((void));
00188 static int tic4x_inst_insert
00189   PARAMS ((tic4x_inst_t *));
00190 static tic4x_inst_t *tic4x_inst_make
00191   PARAMS ((char *, unsigned long, char *));
00192 static int tic4x_inst_add
00193   PARAMS ((tic4x_inst_t *));
00194 void tic4x_end
00195   PARAMS ((void));
00196 static int tic4x_indirect_parse
00197   PARAMS ((tic4x_operand_t *, const tic4x_indirect_t *));
00198 static char *tic4x_operand_parse
00199   PARAMS ((char *, tic4x_operand_t *));
00200 static int tic4x_operands_match
00201   PARAMS ((tic4x_inst_t *, tic4x_insn_t *, int));
00202 static void tic4x_insn_check
00203   PARAMS ((tic4x_insn_t *));
00204 static void tic4x_insn_output
00205   PARAMS ((tic4x_insn_t *));
00206 static int tic4x_operands_parse
00207   PARAMS ((char *, tic4x_operand_t *, int ));
00208 void tic4x_cleanup
00209   PARAMS ((void));
00210 int tic4x_unrecognized_line
00211   PARAMS ((int));
00212 static int tic4x_pc_offset
00213   PARAMS ((unsigned int));
00214 int tic4x_do_align
00215   PARAMS ((int, const char *, int, int));
00216 void tic4x_start_line
00217   PARAMS ((void));
00218 arelent *tc_gen_reloc
00219   PARAMS ((asection *, fixS *));
00220 
00221 
00222 const pseudo_typeS
00223   md_pseudo_table[] =
00224 {
00225   {"align", s_align_bytes, 32},
00226   {"ascii", tic4x_stringer, 1},
00227   {"asciz", tic4x_stringer, 0},
00228   {"asg", tic4x_asg, 0},
00229   {"block", s_space, 4},
00230   {"byte", tic4x_cons, 1},
00231   {"bss", tic4x_bss, 0},
00232   {"copy", s_include, 0},
00233   {"def", tic4x_globl, 0},
00234   {"equ", tic4x_set, 0},
00235   {"eval", tic4x_eval, 0},
00236   {"global", tic4x_globl, 0},
00237   {"globl", tic4x_globl, 0},
00238   {"hword", tic4x_cons, 2},
00239   {"ieee", float_cons, 'i'},
00240   {"int", tic4x_cons, 4},           /* .int allocates 4 bytes.  */
00241   {"ldouble", float_cons, 'e'},
00242   {"newblock", tic4x_newblock, 0},
00243   {"ref", s_ignore, 0},              /* All undefined treated as external.  */
00244   {"set", tic4x_set, 0},
00245   {"sect", tic4x_sect, 1},   /* Define named section.  */
00246   {"space", s_space, 4},
00247   {"string", tic4x_stringer, 0},
00248   {"usect", tic4x_usect, 0},       /* Reserve space in uninit. named sect.  */
00249   {"version", tic4x_version, 0},
00250   {"word", tic4x_cons, 4},   /* .word allocates 4 bytes.  */
00251   {"xdef", tic4x_globl, 0},
00252   {NULL, 0, 0},
00253 };
00254 
00255 int md_short_jump_size = 4;
00256 int md_long_jump_size = 4;
00257 
00258 /* This array holds the chars that always start a comment.  If the
00259    pre-processor is disabled, these aren't very useful.  */
00260 #ifdef TIC4X_ALT_SYNTAX
00261 const char comment_chars[] = ";!";
00262 #else
00263 const char comment_chars[] = ";";
00264 #endif
00265 
00266 /* This array holds the chars that only start a comment at the beginning of
00267    a line.  If the line seems to have the form '# 123 filename'
00268    .line and .file directives will appear in the pre-processed output. 
00269    Note that input_file.c hand checks for '#' at the beginning of the
00270    first line of the input file.  This is because the compiler outputs
00271    #NO_APP at the beginning of its output. 
00272    Also note that comments like this one will always work.  */
00273 const char line_comment_chars[] = "#*";
00274 
00275 /* We needed an unused char for line separation to work around the
00276    lack of macros, using sed and such.  */
00277 const char line_separator_chars[] = "&";
00278 
00279 /* Chars that can be used to separate mant from exp in floating point nums.  */
00280 const char EXP_CHARS[] = "eE";
00281 
00282 /* Chars that mean this number is a floating point constant.  */
00283 /* As in 0f12.456 */
00284 /* or    0d1.2345e12 */
00285 const char FLT_CHARS[] = "fFilsS";
00286 
00287 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
00288    changed in read.c.  Ideally it shouldn't have to know about it at
00289    all, but nothing is ideal around here.  */
00290 
00291 /* Flonums returned here.  */
00292 extern FLONUM_TYPE generic_floating_point_number;
00293 
00294 /* Precision in LittleNums.  */
00295 #define MAX_PRECISION (4)       /* Its a bit overkill for us, but the code
00296                                    requires it... */
00297 #define S_PRECISION (1)            /* Short float constants 16-bit.  */
00298 #define F_PRECISION (2)            /* Float and double types 32-bit.  */
00299 #define E_PRECISION (4)         /* Extended precision, 64-bit (real 40-bit). */
00300 #define GUARD (2)
00301 
00302 /* Turn generic_floating_point_number into a real short/float/double.  */
00303 static int
00304 tic4x_gen_to_words (flonum, words, precision)
00305      FLONUM_TYPE flonum;
00306      LITTLENUM_TYPE *words;
00307      int precision;
00308 {
00309   int return_value = 0;
00310   LITTLENUM_TYPE *p;        /* Littlenum pointer.  */
00311   int mantissa_bits;        /* Bits in mantissa field.  */
00312   int exponent_bits;        /* Bits in exponent field.  */
00313   int exponent;
00314   unsigned int sone;        /* Scaled one.  */
00315   unsigned int sfract;             /* Scaled fraction.  */
00316   unsigned int smant;              /* Scaled mantissa.  */
00317   unsigned int tmp;
00318   unsigned int mover;           /* Mantissa overflow bits */
00319   unsigned int rbit;            /* Round bit. */
00320   int shift;                /* Shift count.  */
00321 
00322   /* NOTE: Svein Seldal <Svein@dev.seldal.com>
00323      The code in this function is altered slightly to support floats
00324      with 31-bits mantissas, thus the documentation below may be a
00325      little bit inaccurate.
00326      
00327      By Michael P. Hayes <m.hayes@elec.canterbury.ac.nz>
00328      Here is how a generic floating point number is stored using
00329      flonums (an extension of bignums) where p is a pointer to an
00330      array of LITTLENUMs.
00331 
00332      For example 2e-3 is stored with exp = -4 and
00333      bits[0] = 0x0000
00334      bits[1] = 0x0000
00335      bits[2] = 0x4fde
00336      bits[3] = 0x978d
00337      bits[4] = 0x126e
00338      bits[5] = 0x0083
00339      with low = &bits[2], high = &bits[5], and leader = &bits[5].
00340 
00341      This number can be written as
00342      0x0083126e978d4fde.00000000 * 65536**-4  or
00343      0x0.0083126e978d4fde        * 65536**0   or
00344      0x0.83126e978d4fde          * 2**-8   = 2e-3
00345 
00346      Note that low points to the 65536**0 littlenum (bits[2]) and
00347      leader points to the most significant non-zero littlenum
00348      (bits[5]).
00349 
00350      TMS320C3X floating point numbers are a bit of a strange beast.
00351      The 32-bit flavour has the 8 MSBs representing the exponent in
00352      twos complement format (-128 to +127).  There is then a sign bit
00353      followed by 23 bits of mantissa.  The mantissa is expressed in
00354      twos complement format with the binary point after the most
00355      significant non sign bit.  The bit after the binary point is
00356      suppressed since it is the complement of the sign bit.  The
00357      effective mantissa is thus 24 bits.  Zero is represented by an
00358      exponent of -128.
00359 
00360      The 16-bit flavour has the 4 MSBs representing the exponent in
00361      twos complement format (-8 to +7).  There is then a sign bit
00362      followed by 11 bits of mantissa.  The mantissa is expressed in
00363      twos complement format with the binary point after the most
00364      significant non sign bit.  The bit after the binary point is
00365      suppressed since it is the complement of the sign bit.  The
00366      effective mantissa is thus 12 bits.  Zero is represented by an
00367      exponent of -8.  For example,
00368 
00369      number       norm mant m  x  e  s  i    fraction f
00370      +0.500 =>  1.00000000000 -1 -1  0  1  .00000000000   (1 + 0) * 2^(-1)
00371      +0.999 =>  1.11111111111 -1 -1  0  1  .11111111111   (1 + 0.99) * 2^(-1)
00372      +1.000 =>  1.00000000000  0  0  0  1  .00000000000   (1 + 0) * 2^(0)
00373      +1.500 =>  1.10000000000  0  0  0  1  .10000000000   (1 + 0.5) * 2^(0)
00374      +1.999 =>  1.11111111111  0  0  0  1  .11111111111   (1 + 0.9) * 2^(0)
00375      +2.000 =>  1.00000000000  1  1  0  1  .00000000000   (1 + 0) * 2^(1)
00376      +4.000 =>  1.00000000000  2  2  0  1  .00000000000   (1 + 0) * 2^(2)
00377      -0.500 =>  1.00000000000 -1 -1  1  0  .10000000000   (-2 + 0) * 2^(-2)
00378      -1.000 =>  1.00000000000  0 -1  1  0  .00000000000   (-2 + 0) * 2^(-1)
00379      -1.500 =>  1.10000000000  0  0  1  0  .10000000000   (-2 + 0.5) * 2^(0)
00380      -1.999 =>  1.11111111111  0  0  1  0  .00000000001   (-2 + 0.11) * 2^(0)
00381      -2.000 =>  1.00000000000  1  1  1  0  .00000000000   (-2 + 0) * 2^(0)
00382      -4.000 =>  1.00000000000  2  1  1  0  .00000000000   (-2 + 0) * 2^(1)
00383 
00384      where e is the exponent, s is the sign bit, i is the implied bit,
00385      and f is the fraction stored in the mantissa field.
00386 
00387      num = (1 + f) * 2^x   =  m * 2^e if s = 0
00388      num = (-2 + f) * 2^x  = -m * 2^e if s = 1
00389      where 0 <= f < 1.0  and 1.0 <= m < 2.0
00390 
00391      The fraction (f) and exponent (e) fields for the TMS320C3X format
00392      can be derived from the normalised mantissa (m) and exponent (x) using:
00393 
00394      f = m - 1, e = x       if s = 0
00395      f = 2 - m, e = x       if s = 1 and m != 1.0
00396      f = 0,     e = x - 1   if s = 1 and m = 1.0
00397      f = 0,     e = -8      if m = 0
00398 
00399 
00400      OK, the other issue we have to consider is rounding since the
00401      mantissa has a much higher potential precision than what we can
00402      represent.  To do this we add half the smallest storable fraction.
00403      We then have to renormalise the number to allow for overflow.
00404 
00405      To convert a generic flonum into a TMS320C3X floating point
00406      number, here's what we try to do....
00407 
00408      The first thing is to generate a normalised mantissa (m) where
00409      1.0 <= m < 2 and to convert the exponent from base 16 to base 2.
00410      We desire the binary point to be placed after the most significant
00411      non zero bit.  This process is done in two steps: firstly, the
00412      littlenum with the most significant non zero bit is located (this
00413      is done for us since leader points to this littlenum) and the
00414      binary point (which is currently after the LSB of the littlenum
00415      pointed to by low) is moved to before the MSB of the littlenum
00416      pointed to by leader.  This requires the exponent to be adjusted
00417      by leader - low + 1.  In the earlier example, the new exponent is
00418      thus -4 + (5 - 2 + 1) = 0 (base 65536).  We now need to convert
00419      the exponent to base 2 by multiplying the exponent by 16 (log2
00420      65536).  The exponent base 2 is thus also zero.
00421 
00422      The second step is to hunt for the most significant non zero bit
00423      in the leader littlenum.  We do this by left shifting a copy of
00424      the leader littlenum until bit 16 is set (0x10000) and counting
00425      the number of shifts, S, required.  The number of shifts then has to
00426      be added to correct the exponent (base 2).  For our example, this
00427      will require 9 shifts and thus our normalised exponent (base 2) is
00428      0 + 9 = 9.  Note that the worst case scenario is when the leader
00429      littlenum is 1, thus requiring 16 shifts.
00430 
00431      We now have to left shift the other littlenums by the same amount,
00432      propagating the shifted bits into the more significant littlenums.
00433      To save a lot of unnecessary shifting we only have to consider
00434      two or three littlenums, since the greatest number of mantissa
00435      bits required is 24 + 1 rounding bit.  While two littlenums
00436      provide 32 bits of precision, the most significant littlenum
00437      may only contain a single significant bit  and thus an extra
00438      littlenum is required.
00439 
00440      Denoting the number of bits in the fraction field as F, we require
00441      G = F + 2 bits (one extra bit is for rounding, the other gets
00442      suppressed).  Say we required S shifts to find the most
00443      significant bit in the leader littlenum, the number of left shifts
00444      required to move this bit into bit position G - 1 is L = G + S - 17.
00445      Note that this shift count may be negative for the short floating
00446      point flavour (where F = 11 and thus G = 13 and potentially S < 3).
00447      If L > 0 we have to shunt the next littlenum into position.  Bit
00448      15 (the MSB) of the next littlenum needs to get moved into position
00449      L - 1 (If L > 15 we need all the bits of this littlenum and
00450      some more from the next one.).  We subtract 16 from L and use this
00451      as the left shift count;  the resultant value we or with the
00452      previous result.  If L > 0, we repeat this operation.   */
00453 
00454   if (precision != S_PRECISION)
00455     words[1] = 0x0000;
00456   if (precision == E_PRECISION)
00457     words[2] = words[3] = 0x0000;
00458 
00459   /* 0.0e0 or NaN seen.  */
00460   if (flonum.low > flonum.leader  /* = 0.0e0 */
00461       || flonum.sign == 0) /* = NaN */
00462     {
00463       if(flonum.sign == 0)
00464         as_bad ("Nan, using zero.");
00465       words[0] = 0x8000;
00466       return return_value;
00467     }
00468 
00469   if (flonum.sign == 'P')
00470     {
00471       /* +INF:  Replace with maximum float.  */
00472       if (precision == S_PRECISION)
00473        words[0] = 0x77ff;
00474       else 
00475        {
00476          words[0] = 0x7f7f;
00477          words[1] = 0xffff;
00478        }
00479       if (precision == E_PRECISION)
00480         {
00481           words[2] = 0x7fff;
00482           words[3] = 0xffff;
00483         }
00484       return return_value;
00485     }
00486   else if (flonum.sign == 'N')
00487     {
00488       /* -INF:  Replace with maximum float.  */
00489       if (precision == S_PRECISION)
00490        words[0] = 0x7800;
00491       else 
00492         words[0] = 0x7f80;
00493       if (precision == E_PRECISION)
00494         words[2] = 0x8000;
00495       return return_value;
00496     }
00497 
00498   exponent = (flonum.exponent + flonum.leader - flonum.low + 1) * 16;
00499 
00500   if (!(tmp = *flonum.leader))
00501     abort ();               /* Hmmm.  */
00502   shift = 0;                /* Find position of first sig. bit.  */
00503   while (tmp >>= 1)
00504     shift++;
00505   exponent -= (16 - shift); /* Adjust exponent.  */
00506 
00507   if (precision == S_PRECISION)    /* Allow 1 rounding bit.  */
00508     {
00509       exponent_bits = 4;
00510       mantissa_bits = 11;
00511     }
00512   else if(precision == F_PRECISION)
00513     {
00514       exponent_bits = 8;
00515       mantissa_bits = 23;
00516     }
00517   else /* E_PRECISION */
00518     {
00519       exponent_bits = 8;
00520       mantissa_bits = 31;
00521     }
00522 
00523   shift = mantissa_bits - shift;
00524 
00525   smant = 0;
00526   mover = 0;
00527   rbit = 0;
00528   /* Store the mantissa data into smant and the roundbit into rbit */
00529   for (p = flonum.leader; p >= flonum.low && shift > -16; p--)
00530     {
00531       tmp = shift >= 0 ? *p << shift : *p >> -shift;
00532       rbit = shift < 0 ? ((*p >> (-shift-1)) & 0x1) : 0;
00533       smant |= tmp;
00534       shift -= 16;
00535     }
00536 
00537   /* OK, we've got our scaled mantissa so let's round it up */
00538   if(rbit)
00539     {
00540       /* If the mantissa is going to overflow when added, lets store
00541          the extra bit in mover. -- A special case exists when
00542          mantissa_bits is 31 (E_PRECISION). Then the first test cannot
00543          be trusted, as result is host-dependent, thus the second
00544          test. */
00545       if( smant == ((unsigned)(1<<(mantissa_bits+1))-1)
00546           || smant == (unsigned)-1 )  /* This is to catch E_PRECISION cases */
00547         mover=1;
00548       smant++;
00549     }
00550 
00551   /* Get the scaled one value */
00552   sone = (1 << (mantissa_bits));
00553 
00554   /* The number may be unnormalised so renormalise it...  */
00555   if(mover)
00556     {
00557       smant >>= 1;
00558       smant |= sone; /* Insert the bit from mover into smant */
00559       exponent++;
00560     }
00561 
00562   /* The binary point is now between bit positions 11 and 10 or 23 and 22,
00563      i.e., between mantissa_bits - 1 and mantissa_bits - 2 and the
00564      bit at mantissa_bits - 1 should be set.  */
00565   if (!(sone&smant))
00566     abort ();                   /* Ooops.  */
00567 
00568   if (flonum.sign == '+')
00569     sfract = smant - sone;  /* smant - 1.0.  */
00570   else
00571     {
00572       /* This seems to work.  */
00573       if (smant == sone)
00574        {
00575          exponent--;
00576          sfract = 0;
00577        }
00578       else
00579         {
00580           sfract = -smant & (sone-1);   /* 2.0 - smant.  */
00581         }
00582       sfract |= sone;              /* Insert sign bit.  */
00583     }
00584 
00585   if (abs (exponent) >= (1 << (exponent_bits - 1)))
00586     as_bad ("Cannot represent exponent in %d bits", exponent_bits);
00587 
00588   /* Force exponent to fit in desired field width.  */
00589   exponent &= (1 << (exponent_bits)) - 1;
00590 
00591   if (precision == E_PRECISION)
00592     {
00593       /* Map the float part first (100% equal format as F_PRECISION) */
00594       words[0]  = exponent << (mantissa_bits+1-24);
00595       words[0] |= sfract >> 24;
00596       words[1]  = sfract >> 8;
00597 
00598       /* Map the mantissa in the next */
00599       words[2]  = sfract >> 16;
00600       words[3]  = sfract & 0xffff;
00601     }
00602   else
00603     {
00604       /* Insert the exponent data into the word */
00605       sfract |= exponent << (mantissa_bits+1);
00606 
00607       if (precision == S_PRECISION)
00608         words[0] = sfract;
00609       else
00610         {
00611           words[0] = sfract >> 16;
00612           words[1] = sfract & 0xffff;
00613         }
00614     }
00615 
00616   return return_value;
00617 }
00618 
00619 /* Returns pointer past text consumed.  */
00620 static char *
00621 tic4x_atof (str, what_kind, words)
00622      char *str;
00623      char what_kind;
00624      LITTLENUM_TYPE *words;
00625 {
00626   /* Extra bits for zeroed low-order bits.  The 1st MAX_PRECISION are
00627      zeroed, the last contain flonum bits.  */
00628   static LITTLENUM_TYPE bits[MAX_PRECISION + MAX_PRECISION + GUARD];
00629   char *return_value;
00630   /* Number of 16-bit words in the format.  */
00631   int precision;
00632   FLONUM_TYPE save_gen_flonum;
00633 
00634   /* We have to save the generic_floating_point_number because it
00635      contains storage allocation about the array of LITTLENUMs where
00636      the value is actually stored.  We will allocate our own array of
00637      littlenums below, but have to restore the global one on exit.  */
00638   save_gen_flonum = generic_floating_point_number;
00639 
00640   return_value = str;
00641   generic_floating_point_number.low = bits + MAX_PRECISION;
00642   generic_floating_point_number.high = NULL;
00643   generic_floating_point_number.leader = NULL;
00644   generic_floating_point_number.exponent = 0;
00645   generic_floating_point_number.sign = '\0';
00646 
00647   /* Use more LittleNums than seems necessary: the highest flonum may
00648      have 15 leading 0 bits, so could be useless.  */
00649 
00650   memset (bits, '\0', sizeof (LITTLENUM_TYPE) * MAX_PRECISION);
00651 
00652   switch (what_kind)
00653     {
00654     case 's':
00655     case 'S':
00656       precision = S_PRECISION;
00657       break;
00658 
00659     case 'd':
00660     case 'D':
00661     case 'f':
00662     case 'F':
00663       precision = F_PRECISION;
00664       break;
00665 
00666     case 'E':
00667     case 'e':
00668       precision = E_PRECISION;
00669       break;
00670 
00671     default:
00672       as_bad ("Invalid floating point number");
00673       return (NULL);
00674     }
00675 
00676   generic_floating_point_number.high
00677     = generic_floating_point_number.low + precision - 1 + GUARD;
00678 
00679   if (atof_generic (&return_value, ".", EXP_CHARS,
00680                   &generic_floating_point_number))
00681     {
00682       as_bad ("Invalid floating point number");
00683       return (NULL);
00684     }
00685 
00686   tic4x_gen_to_words (generic_floating_point_number,
00687                   words, precision);
00688 
00689   /* Restore the generic_floating_point_number's storage alloc (and
00690      everything else).  */
00691   generic_floating_point_number = save_gen_flonum;
00692 
00693   return return_value;
00694 }
00695 
00696 static void 
00697 tic4x_insert_reg (regname, regnum)
00698      char *regname;
00699      int regnum;
00700 {
00701   char buf[32];
00702   int i;
00703 
00704   symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
00705                                &zero_address_frag));
00706   for (i = 0; regname[i]; i++)
00707     buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
00708   buf[i] = '\0';
00709 
00710   symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
00711                                &zero_address_frag));
00712 }
00713 
00714 static void 
00715 tic4x_insert_sym (symname, value)
00716      char *symname;
00717      int value;
00718 {
00719   symbolS *symbolP;
00720 
00721   symbolP = symbol_new (symname, absolute_section,
00722                      (valueT) value, &zero_address_frag);
00723   SF_SET_LOCAL (symbolP);
00724   symbol_table_insert (symbolP);
00725 }
00726 
00727 static char *
00728 tic4x_expression (str, exp)
00729      char *str;
00730      expressionS *exp;
00731 {
00732   char *s;
00733   char *t;
00734 
00735   t = input_line_pointer;   /* Save line pointer.  */
00736   input_line_pointer = str;
00737   expression (exp);
00738   s = input_line_pointer;
00739   input_line_pointer = t;   /* Restore line pointer.  */
00740   return s;                 /* Return pointer to where parsing stopped.  */
00741 }
00742 
00743 static char *
00744 tic4x_expression_abs (str, value)
00745      char *str;
00746      offsetT *value;
00747 {
00748   char *s;
00749   char *t;
00750 
00751   t = input_line_pointer;   /* Save line pointer.  */
00752   input_line_pointer = str;
00753   *value = get_absolute_expression ();
00754   s = input_line_pointer;
00755   input_line_pointer = t;   /* Restore line pointer.  */
00756   return s;
00757 }
00758 
00759 static void 
00760 tic4x_emit_char (c,b)
00761      char c;
00762      int b;
00763 {
00764   expressionS exp;
00765 
00766   exp.X_op = O_constant;
00767   exp.X_add_number = c;
00768   emit_expr (&exp, b);
00769 }
00770 
00771 static void 
00772 tic4x_seg_alloc (name, seg, size, symbolP)
00773      char *name ATTRIBUTE_UNUSED;
00774      segT seg ATTRIBUTE_UNUSED;
00775      int size;
00776      symbolS *symbolP;
00777 {
00778   /* Note that the size is in words
00779      so we multiply it by 4 to get the number of bytes to allocate.  */
00780 
00781   /* If we have symbol:  .usect  ".fred", size etc.,
00782      the symbol needs to point to the first location reserved
00783      by the pseudo op.  */
00784 
00785   if (size)
00786     {
00787       char *p;
00788 
00789       p = frag_var (rs_fill, 1, 1, (relax_substateT) 0,
00790                   (symbolS *) symbolP,
00791                   size * OCTETS_PER_BYTE, (char *) 0);
00792       *p = 0;
00793     }
00794 }
00795 
00796 /* .asg ["]character-string["], symbol */
00797 static void 
00798 tic4x_asg (x)
00799      int x ATTRIBUTE_UNUSED;
00800 {
00801   char c;
00802   char *name;
00803   char *str;
00804   char *tmp;
00805 
00806   SKIP_WHITESPACE ();
00807   str = input_line_pointer;
00808 
00809   /* Skip string expression.  */
00810   while (*input_line_pointer != ',' && *input_line_pointer)
00811     input_line_pointer++;
00812   if (*input_line_pointer != ',')
00813     {
00814       as_bad ("Comma expected\n");
00815       return;
00816     }
00817   *input_line_pointer++ = '\0';
00818   name = input_line_pointer;
00819   c = get_symbol_end ();    /* Get terminator.  */
00820   tmp = xmalloc (strlen (str) + 1);
00821   strcpy (tmp, str);
00822   str = tmp;
00823   tmp = xmalloc (strlen (name) + 1);
00824   strcpy (tmp, name);
00825   name = tmp;
00826   if (hash_find (tic4x_asg_hash, name))
00827     hash_replace (tic4x_asg_hash, name, (PTR) str);
00828   else
00829     hash_insert (tic4x_asg_hash, name, (PTR) str);
00830   *input_line_pointer = c;
00831   demand_empty_rest_of_line ();
00832 }
00833 
00834 /* .bss symbol, size  */
00835 static void 
00836 tic4x_bss (x)
00837      int x ATTRIBUTE_UNUSED;
00838 {
00839   char c;
00840   char *name;
00841   char *p;
00842   offsetT size;
00843   segT current_seg;
00844   subsegT current_subseg;
00845   symbolS *symbolP;
00846 
00847   current_seg = now_seg;    /* Save current seg.  */
00848   current_subseg = now_subseg;     /* Save current subseg.  */
00849 
00850   SKIP_WHITESPACE ();
00851   name = input_line_pointer;
00852   c = get_symbol_end ();    /* Get terminator.  */
00853   if (c != ',')
00854     {
00855       as_bad (".bss size argument missing\n");
00856       return;
00857     }
00858 
00859   input_line_pointer =
00860     tic4x_expression_abs (++input_line_pointer, &size);
00861   if (size < 0)
00862     {
00863       as_bad (".bss size %ld < 0!", (long) size);
00864       return;
00865     }
00866   subseg_set (bss_section, 0);
00867   symbolP = symbol_find_or_make (name);
00868 
00869   if (S_GET_SEGMENT (symbolP) == bss_section)
00870     symbol_get_frag (symbolP)->fr_symbol = 0;
00871 
00872   symbol_set_frag (symbolP, frag_now);
00873 
00874   p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
00875               size * OCTETS_PER_BYTE, (char *) 0);
00876   *p = 0;                   /* Fill char.  */
00877 
00878   S_SET_SEGMENT (symbolP, bss_section);
00879 
00880   /* The symbol may already have been created with a preceding
00881      ".globl" directive -- be careful not to step on storage class
00882      in that case.  Otherwise, set it to static.  */
00883   if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
00884     S_SET_STORAGE_CLASS (symbolP, C_STAT);
00885 
00886   subseg_set (current_seg, current_subseg); /* Restore current seg.  */
00887   demand_empty_rest_of_line ();
00888 }
00889 
00890 static void
00891 tic4x_globl (ignore)
00892      int ignore ATTRIBUTE_UNUSED;
00893 {
00894   char *name;
00895   int c;
00896   symbolS *symbolP;
00897 
00898   do
00899     {
00900       name = input_line_pointer;
00901       c = get_symbol_end ();
00902       symbolP = symbol_find_or_make (name);
00903       *input_line_pointer = c;
00904       SKIP_WHITESPACE ();
00905       S_SET_STORAGE_CLASS (symbolP, C_EXT);
00906       if (c == ',')
00907        {
00908          input_line_pointer++;
00909          SKIP_WHITESPACE ();
00910          if (*input_line_pointer == '\n')
00911            c = '\n';
00912        }
00913     }
00914   while (c == ',');
00915 
00916   demand_empty_rest_of_line ();
00917 }
00918 
00919 /* Handle .byte, .word. .int, .long */
00920 static void 
00921 tic4x_cons (bytes)
00922      int bytes;
00923 {
00924   register unsigned int c;
00925   do
00926     {
00927       SKIP_WHITESPACE ();
00928       if (*input_line_pointer == '"')
00929        {
00930          input_line_pointer++;
00931          while (is_a_char (c = next_char_of_string ()))
00932            tic4x_emit_char (c, 4);
00933          know (input_line_pointer[-1] == '\"');
00934        }
00935       else
00936        {
00937          expressionS exp;
00938 
00939          input_line_pointer = tic4x_expression (input_line_pointer, &exp);
00940          if (exp.X_op == O_constant)
00941            {
00942              switch (bytes)
00943               {
00944               case 1:
00945                 exp.X_add_number &= 255;
00946                 break;
00947               case 2:
00948                 exp.X_add_number &= 65535;
00949                 break;
00950               }
00951            }
00952          /* Perhaps we should disallow .byte and .hword with
00953             a non constant expression that will require relocation.  */
00954          emit_expr (&exp, 4);
00955        }
00956     }
00957   while (*input_line_pointer++ == ',');
00958 
00959   input_line_pointer--;            /* Put terminator back into stream.  */
00960   demand_empty_rest_of_line ();
00961 }
00962 
00963 /* Handle .ascii, .asciz, .string */
00964 static void 
00965 tic4x_stringer (append_zero)
00966      int append_zero; /*ex: bytes */
00967 {
00968   int bytes;
00969   register unsigned int c;
00970 
00971   bytes = 0;
00972   do
00973     {
00974       SKIP_WHITESPACE ();
00975       if (*input_line_pointer == '"')
00976        {
00977          input_line_pointer++;
00978          while (is_a_char (c = next_char_of_string ()))
00979             {
00980               tic4x_emit_char (c, 1);
00981               bytes++;
00982             }
00983 
00984           if (append_zero)
00985             {
00986               tic4x_emit_char (c, 1);
00987               bytes++;
00988             }
00989 
00990          know (input_line_pointer[-1] == '\"');
00991        }
00992       else
00993        {
00994          expressionS exp;
00995 
00996          input_line_pointer = tic4x_expression (input_line_pointer, &exp);
00997          if (exp.X_op != O_constant)
00998             {
00999               as_bad("Non-constant symbols not allowed\n");
01000               return;
01001             }
01002           exp.X_add_number &= 255; /* Limit numeber to 8-bit */
01003          emit_expr (&exp, 1);
01004           bytes++;
01005        }
01006     }
01007   while (*input_line_pointer++ == ',');
01008 
01009   /* Fill out the rest of the expression with 0's to fill up a full word */
01010   if ( bytes&0x3 )
01011     tic4x_emit_char (0, 4-(bytes&0x3));
01012 
01013   input_line_pointer--;            /* Put terminator back into stream.  */
01014   demand_empty_rest_of_line ();
01015 }
01016 
01017 /* .eval expression, symbol */
01018 static void 
01019 tic4x_eval (x)
01020      int x ATTRIBUTE_UNUSED;
01021 {
01022   char c;
01023   offsetT value;
01024   char *name;
01025 
01026   SKIP_WHITESPACE ();
01027   input_line_pointer =
01028     tic4x_expression_abs (input_line_pointer, &value);
01029   if (*input_line_pointer++ != ',')
01030     {
01031       as_bad ("Symbol missing\n");
01032       return;
01033     }
01034   name = input_line_pointer;
01035   c = get_symbol_end ();    /* Get terminator.  */
01036   demand_empty_rest_of_line ();
01037   tic4x_insert_sym (name, value);
01038 }
01039 
01040 /* Reset local labels.  */
01041 static void 
01042 tic4x_newblock (x)
01043      int x ATTRIBUTE_UNUSED;
01044 {
01045   dollar_label_clear ();
01046 }
01047 
01048 /* .sect "section-name" [, value] */
01049 /* .sect ["]section-name[:subsection-name]["] [, value] */
01050 static void 
01051 tic4x_sect (x)
01052      int x ATTRIBUTE_UNUSED;
01053 {
01054   char c;
01055   char *section_name;
01056   char *subsection_name;
01057   char *name;
01058   segT seg;
01059   offsetT num;
01060 
01061   SKIP_WHITESPACE ();
01062   if (*input_line_pointer == '"')
01063     input_line_pointer++;
01064   section_name = input_line_pointer;
01065   c = get_symbol_end ();    /* Get terminator.  */
01066   input_line_pointer++;            /* Skip null symbol terminator.  */
01067   name = xmalloc (input_line_pointer - section_name + 1);
01068   strcpy (name, section_name);
01069 
01070   /* TI C from version 5.0 allows a section name to contain a
01071      subsection name as well. The subsection name is separated by a
01072      ':' from the section name.  Currently we scan the subsection
01073      name and discard it.
01074      Volker Kuhlmann  <v.kuhlmann@elec.canterbury.ac.nz>.  */
01075   if (c == ':')
01076     {
01077       subsection_name = input_line_pointer;
01078       c = get_symbol_end ();       /* Get terminator.  */
01079       input_line_pointer++; /* Skip null symbol terminator.  */
01080       as_warn (".sect: subsection name ignored");
01081     }
01082 
01083   /* We might still have a '"' to discard, but the character after a
01084      symbol name will be overwritten with a \0 by get_symbol_end()
01085      [VK].  */
01086 
01087   if (c == ',')
01088     input_line_pointer =
01089       tic4x_expression_abs (input_line_pointer, &num);
01090   else if (*input_line_pointer == ',')
01091     {
01092       input_line_pointer =
01093        tic4x_expression_abs (++input_line_pointer, &num);
01094     }
01095   else
01096     num = 0;
01097 
01098   seg = subseg_new (name, num);
01099   if (line_label != NULL)
01100     {
01101       S_SET_SEGMENT (line_label, seg);
01102       symbol_set_frag (line_label, frag_now);
01103     }
01104 
01105   if (bfd_get_section_flags (stdoutput, seg) == SEC_NO_FLAGS)
01106     {
01107       if (!bfd_set_section_flags (stdoutput, seg, SEC_DATA))
01108        as_warn ("Error setting flags for \"%s\": %s", name,
01109                bfd_errmsg (bfd_get_error ()));
01110     }
01111 
01112   /* If the last character overwritten by get_symbol_end() was an
01113      end-of-line, we must restore it or the end of the line will not be
01114      recognised and scanning extends into the next line, stopping with
01115      an error (blame Volker Kuhlmann <v.kuhlmann@elec.canterbury.ac.nz>
01116      if this is not true).  */
01117   if (is_end_of_line[(unsigned char) c])
01118     *(--input_line_pointer) = c;
01119 
01120   demand_empty_rest_of_line ();
01121 }
01122 
01123 /* symbol[:] .set value  or  .set symbol, value */
01124 static void 
01125 tic4x_set (x)
01126      int x ATTRIBUTE_UNUSED;
01127 {
01128   symbolS *symbolP;
01129 
01130   SKIP_WHITESPACE ();
01131   if ((symbolP = line_label) == NULL)
01132     {
01133       char c;
01134       char *name;
01135 
01136       name = input_line_pointer;
01137       c = get_symbol_end ();       /* Get terminator.  */
01138       if (c != ',')
01139        {
01140          as_bad (".set syntax invalid\n");
01141          ignore_rest_of_line ();
01142          return;
01143        }
01144       ++input_line_pointer;
01145       symbolP = symbol_find_or_make (name);
01146     }
01147   else
01148     symbol_table_insert (symbolP);
01149 
01150   pseudo_set (symbolP);
01151   demand_empty_rest_of_line ();
01152 }
01153 
01154 /* [symbol] .usect ["]section-name["], size-in-words [, alignment-flag] */
01155 static void 
01156 tic4x_usect (x)
01157      int x ATTRIBUTE_UNUSED;
01158 {
01159   char c;
01160   char *name;
01161   char *section_name;
01162   segT seg;
01163   offsetT size, alignment_flag;
01164   segT current_seg;
01165   subsegT current_subseg;
01166 
01167   current_seg = now_seg;    /* save current seg.  */
01168   current_subseg = now_subseg;     /* save current subseg.  */
01169 
01170   SKIP_WHITESPACE ();
01171   if (*input_line_pointer == '"')
01172     input_line_pointer++;
01173   section_name = input_line_pointer;
01174   c = get_symbol_end ();    /* Get terminator.  */
01175   input_line_pointer++;            /* Skip null symbol terminator.  */
01176   name = xmalloc (input_line_pointer - section_name + 1);
01177   strcpy (name, section_name);
01178 
01179   if (c == ',')
01180     input_line_pointer =
01181       tic4x_expression_abs (input_line_pointer, &size);
01182   else if (*input_line_pointer == ',')
01183     {
01184       input_line_pointer =
01185        tic4x_expression_abs (++input_line_pointer, &size);
01186     }
01187   else
01188     size = 0;
01189 
01190   /* Read a possibly present third argument (alignment flag) [VK].  */
01191   if (*input_line_pointer == ',')
01192     {
01193       input_line_pointer =
01194        tic4x_expression_abs (++input_line_pointer, &alignment_flag);
01195     }
01196   else
01197     alignment_flag = 0;
01198   if (alignment_flag)
01199     as_warn (".usect: non-zero alignment flag ignored");
01200 
01201   seg = subseg_new (name, 0);
01202   if (line_label != NULL)
01203     {
01204       S_SET_SEGMENT (line_label, seg);
01205       symbol_set_frag (line_label, frag_now);
01206       S_SET_VALUE (line_label, frag_now_fix ());
01207     }
01208   seg_info (seg)->bss = 1;  /* Uninitialised data.  */
01209   if (!bfd_set_section_flags (stdoutput, seg, SEC_ALLOC))
01210     as_warn ("Error setting flags for \"%s\": %s", name,
01211             bfd_errmsg (bfd_get_error ()));
01212   tic4x_seg_alloc (name, seg, size, line_label);
01213 
01214   if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
01215     S_SET_STORAGE_CLASS (line_label, C_STAT);
01216 
01217   subseg_set (current_seg, current_subseg);      /* Restore current seg.  */
01218   demand_empty_rest_of_line ();
01219 }
01220 
01221 /* .version cpu-version.  */
01222 static void 
01223 tic4x_version (x)
01224      int x ATTRIBUTE_UNUSED;
01225 {
01226   offsetT temp;
01227 
01228   input_line_pointer =
01229     tic4x_expression_abs (input_line_pointer, &temp);
01230   if (!IS_CPU_TIC3X (temp) && !IS_CPU_TIC4X (temp))
01231     as_bad ("This assembler does not support processor generation %ld",
01232            (long) temp);
01233 
01234   if (tic4x_cpu && temp != (offsetT) tic4x_cpu)
01235     as_warn ("Changing processor generation on fly not supported...");
01236   tic4x_cpu = temp;
01237   demand_empty_rest_of_line ();
01238 }
01239 
01240 static void 
01241 tic4x_init_regtable ()
01242 {
01243   unsigned int i;
01244 
01245   for (i = 0; i < tic3x_num_registers; i++)
01246     tic4x_insert_reg (tic3x_registers[i].name,
01247                   tic3x_registers[i].regno);
01248 
01249   if (IS_CPU_TIC4X (tic4x_cpu))
01250     {
01251       /* Add additional Tic4x registers, overriding some C3x ones.  */
01252       for (i = 0; i < tic4x_num_registers; i++)
01253        tic4x_insert_reg (tic4x_registers[i].name,
01254                      tic4x_registers[i].regno);
01255     }
01256 }
01257 
01258 static void 
01259 tic4x_init_symbols ()
01260 {
01261   /* The TI tools accept case insensitive versions of these symbols,
01262      we don't !
01263 
01264      For TI C/Asm 5.0
01265 
01266      .TMS320xx       30,31,32,40,or 44       set according to -v flag
01267      .C3X or .C3x    1 or 0                  1 if -v30,-v31,or -v32
01268      .C30            1 or 0                  1 if -v30
01269      .C31            1 or 0                  1 if -v31
01270      .C32            1 or 0                  1 if -v32
01271      .C4X or .C4x    1 or 0                  1 if -v40, or -v44
01272      .C40            1 or 0                  1 if -v40
01273      .C44            1 or 0                  1 if -v44
01274 
01275      .REGPARM 1 or 0                  1 if -mr option used
01276      .BIGMODEL        1 or 0                  1 if -mb option used
01277 
01278      These symbols are currently supported but will be removed in a
01279      later version:
01280      .TMS320C30      1 or 0                  1 if -v30,-v31,or -v32
01281      .TMS320C31      1 or 0                  1 if -v31
01282      .TMS320C32      1 or 0                  1 if -v32
01283      .TMS320C40      1 or 0                  1 if -v40, or -v44
01284      .TMS320C44      1 or 0                  1 if -v44
01285 
01286      Source: TI: TMS320C3x/C4x Assembly Language Tools User's Guide,
01287      1997, SPRU035C, p. 3-17/3-18.  */
01288   tic4x_insert_sym (".REGPARM", tic4x_reg_args);
01289   tic4x_insert_sym (".MEMPARM", !tic4x_reg_args);       
01290   tic4x_insert_sym (".BIGMODEL", tic4x_big_model);
01291   tic4x_insert_sym (".C30INTERRUPT", 0);
01292   tic4x_insert_sym (".TMS320xx", tic4x_cpu == 0 ? 40 : tic4x_cpu);
01293   tic4x_insert_sym (".C3X", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
01294   tic4x_insert_sym (".C3x", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
01295   tic4x_insert_sym (".C4X", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
01296   tic4x_insert_sym (".C4x", tic4x_cpu == 0 || tic4x_cpu == 40 || tic4x_cpu == 44);
01297   /* Do we need to have the following symbols also in lower case?  */
01298   tic4x_insert_sym (".TMS320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
01299   tic4x_insert_sym (".tms320C30", tic4x_cpu == 30 || tic4x_cpu == 31 || tic4x_cpu == 32 || tic4x_cpu == 33);
01300   tic4x_insert_sym (".TMS320C31", tic4x_cpu == 31);
01301   tic4x_insert_sym (".tms320C31", tic4x_cpu == 31);
01302   tic4x_insert_sym (".TMS320C32", tic4x_cpu == 32);
01303   tic4x_insert_sym (".tms320C32", tic4x_cpu == 32);
01304   tic4x_insert_sym (".TMS320C33", tic4x_cpu == 33);
01305   tic4x_insert_sym (".tms320C33", tic4x_cpu == 33);
01306   tic4x_insert_sym (".TMS320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
01307   tic4x_insert_sym (".tms320C40", tic4x_cpu == 40 || tic4x_cpu == 44 || tic4x_cpu == 0);
01308   tic4x_insert_sym (".TMS320C44", tic4x_cpu == 44);
01309   tic4x_insert_sym (".tms320C44", tic4x_cpu == 44);
01310   tic4x_insert_sym (".TMX320C40", 0);     /* C40 first pass silicon ?  */
01311   tic4x_insert_sym (".tmx320C40", 0);
01312 }
01313 
01314 /* Insert a new instruction template into hash table.  */
01315 static int 
01316 tic4x_inst_insert (inst)
01317      tic4x_inst_t *inst;
01318 {
01319   static char prev_name[16];
01320   const char *retval = NULL;
01321 
01322   /* Only insert the first name if have several similar entries.  */
01323   if (!strcmp (inst->name, prev_name) || inst->name[0] == '\0')
01324     return 1;
01325 
01326   retval = hash_insert (tic4x_op_hash, inst->name, (PTR) inst);
01327   if (retval != NULL)
01328     fprintf (stderr, "internal error: can't hash `%s': %s\n",
01329             inst->name, retval);
01330   else
01331     strcpy (prev_name, inst->name);
01332   return retval == NULL;
01333 }
01334 
01335 /* Make a new instruction template.  */
01336 static tic4x_inst_t *
01337 tic4x_inst_make (name, opcode, args)
01338      char *name;
01339      unsigned long opcode;
01340      char *args;
01341 {
01342   static tic4x_inst_t *insts = NULL;
01343   static char *names = NULL;
01344   static int index = 0;
01345 
01346   if (insts == NULL)
01347     {
01348       /* Allocate memory to store name strings.  */
01349       names = (char *) xmalloc (sizeof (char) * 8192);
01350       /* Allocate memory for additional insts.  */
01351       insts = (tic4x_inst_t *)
01352        xmalloc (sizeof (tic4x_inst_t) * 1024);
01353     }
01354   insts[index].name = names;
01355   insts[index].opcode = opcode;
01356   insts[index].opmask = 0xffffffff;
01357   insts[index].args = args;
01358   index++;
01359 
01360   do
01361     *names++ = *name++;
01362   while (*name);
01363   *names++ = '\0';
01364 
01365   return &insts[index - 1];
01366 }
01367 
01368 /* Add instruction template, creating dynamic templates as required.  */
01369 static int 
01370 tic4x_inst_add (insts)
01371      tic4x_inst_t *insts;
01372 {
01373   char *s = insts->name;
01374   char *d;
01375   unsigned int i;
01376   int ok = 1;
01377   char name[16];
01378 
01379   d = name;
01380 
01381   /* We do not care about INSNs that is not a part of our
01382      oplevel setting */
01383   if (!insts->oplevel & tic4x_oplevel)
01384     return ok;
01385 
01386   while (1)
01387     {
01388       switch (*s)
01389        {
01390        case 'B':
01391        case 'C':
01392          /* Dynamically create all the conditional insts.  */
01393          for (i = 0; i < tic4x_num_conds; i++)
01394            {
01395              tic4x_inst_t *inst;
01396              int k = 0;
01397              char *c = tic4x_conds[i].name;
01398              char *e = d;
01399 
01400              while (*c)
01401               *e++ = *c++;
01402              c = s + 1;
01403              while (*c)
01404               *e++ = *c++;
01405              *e = '\0';
01406 
01407              /* If instruction found then have already processed it.  */
01408              if (hash_find (tic4x_op_hash, name))
01409               return 1;
01410 
01411              do
01412               {
01413                 inst = tic4x_inst_make (name, insts[k].opcode +
01414                                    (tic4x_conds[i].cond <<
01415                                     (*s == 'B' ? 16 : 23)),
01416                                    insts[k].args);
01417                 if (k == 0) /* Save strcmp() with following func.  */
01418                   ok &= tic4x_inst_insert (inst);
01419                 k++;
01420               }
01421              while (!strcmp (insts->name,
01422                            insts[k].name));
01423            }
01424          return ok;
01425          break;
01426 
01427        case '\0':
01428          return tic4x_inst_insert (insts);
01429          break;
01430 
01431        default:
01432          *d++ = *s++;
01433          break;
01434        }
01435     }
01436 }
01437 
01438 /* This function is called once, at assembler startup time.  It should
01439    set up all the tables, etc., that the MD part of the assembler will
01440    need.  */
01441 void 
01442 md_begin ()
01443 {
01444   int ok = 1;
01445   unsigned int i;
01446 
01447   /* Setup the proper opcode level according to the
01448      commandline parameters */
01449   tic4x_oplevel = OP_C3X;
01450 
01451   if ( IS_CPU_TIC4X(tic4x_cpu) )
01452     tic4x_oplevel |= OP_C4X;
01453 
01454   if ( (   tic4x_cpu == 31 && tic4x_revision >= 6)
01455        || (tic4x_cpu == 32 && tic4x_revision >= 2)
01456        || (tic4x_cpu == 33)
01457        || tic4x_enhanced )
01458     tic4x_oplevel |= OP_ENH;
01459 
01460   if ( (   tic4x_cpu == 30 && tic4x_revision >= 7)
01461        || (tic4x_cpu == 31 && tic4x_revision >= 5)
01462        || (tic4x_cpu == 32)
01463        || tic4x_lowpower )
01464     tic4x_oplevel |= OP_LPWR;
01465 
01466   if ( (   tic4x_cpu == 30 && tic4x_revision >= 7)
01467        || (tic4x_cpu == 31 && tic4x_revision >= 5)
01468        || (tic4x_cpu == 32)
01469        || (tic4x_cpu == 33)
01470        || (tic4x_cpu == 40 && tic4x_revision >= 5)
01471        || (tic4x_cpu == 44)
01472        || tic4x_idle2 )
01473     tic4x_oplevel |= OP_IDLE2;
01474 
01475   /* Create hash table for mnemonics.  */
01476   tic4x_op_hash = hash_new ();
01477 
01478   /* Create hash table for asg pseudo.  */
01479   tic4x_asg_hash = hash_new ();
01480 
01481   /* Add mnemonics to hash table, expanding conditional mnemonics on fly.  */
01482   for (i = 0; i < tic4x_num_insts; i++)
01483     ok &= tic4x_inst_add ((void *) &tic4x_insts[i]);
01484 
01485   /* Create dummy inst to avoid errors accessing end of table.  */
01486   tic4x_inst_make ("", 0, "");
01487 
01488   if (!ok)
01489     as_fatal ("Broken assembler.  No assembly attempted.");
01490 
01491   /* Add registers to symbol table.  */
01492   tic4x_init_regtable ();
01493 
01494   /* Add predefined symbols to symbol table.  */
01495   tic4x_init_symbols ();
01496 }
01497 
01498 void 
01499 tic4x_end ()
01500 {
01501   bfd_set_arch_mach (stdoutput, bfd_arch_tic4x, 
01502                    IS_CPU_TIC4X (tic4x_cpu) ? bfd_mach_tic4x : bfd_mach_tic3x);
01503 }
01504 
01505 static int 
01506 tic4x_indirect_parse (operand, indirect)
01507      tic4x_operand_t *operand;
01508      const tic4x_indirect_t *indirect;
01509 {
01510   char *n = indirect->name;
01511   char *s = input_line_pointer;
01512   char *b;
01513   symbolS *symbolP;
01514   char name[32];
01515 
01516   operand->disp = 0;
01517   for (; *n; n++)
01518     {
01519       switch (*n)
01520        {
01521        case 'a':            /* Need to match aux register.  */
01522          b = name;
01523 #ifdef TIC4X_ALT_SYNTAX
01524          if (*s == '%')
01525            s++;
01526 #endif
01527          while (ISALNUM (*s))
01528            *b++ = *s++;
01529          *b++ = '\0';
01530          if (!(symbolP = symbol_find (name)))
01531            return 0;
01532 
01533          if (S_GET_SEGMENT (symbolP) != reg_section)
01534            return 0;
01535 
01536          operand->aregno = S_GET_VALUE (symbolP);
01537          if (operand->aregno >= REG_AR0 && operand->aregno <= REG_AR7)
01538            break;
01539 
01540          as_bad ("Auxiliary register AR0--AR7 required for indirect");
01541          return -1;
01542 
01543        case 'd':            /* Need to match constant for disp.  */
01544 #ifdef TIC4X_ALT_SYNTAX
01545          if (*s == '%')     /* expr() will die if we don't skip this.  */
01546            s++;
01547 #endif
01548          s = tic4x_expression (s, &operand->expr);
01549          if (operand->expr.X_op != O_constant)
01550            return 0;
01551          operand->disp = operand->expr.X_add_number;
01552          if (operand->disp < 0 || operand->disp > 255)
01553            {
01554              as_bad ("Bad displacement %d (require 0--255)\n",
01555                     operand->disp);
01556              return -1;
01557            }
01558          break;
01559 
01560        case 'y':            /* Need to match IR0.  */
01561        case 'z':            /* Need to match IR1.  */
01562 #ifdef TIC4X_ALT_SYNTAX
01563          if (*s == '%')
01564            s++;
01565 #endif
01566          s = tic4x_expression (s, &operand->expr);
01567          if (operand->expr.X_op != O_register)
01568            return 0;
01569          if (operand->expr.X_add_number != REG_IR0
01570              && operand->expr.X_add_number != REG_IR1)
01571            {
01572              as_bad ("Index register IR0,IR1 required for displacement");
01573              return -1;
01574            }
01575 
01576          if (*n == 'y' && operand->expr.X_add_number == REG_IR0)
01577            break;
01578          if (*n == 'z' && operand->expr.X_add_number == REG_IR1)
01579            break;
01580          return 0;
01581 
01582        case '(':
01583          if (*s != '(')     /* No displacement, assume to be 1.  */
01584            {
01585              operand->disp = 1;
01586              while (*n != ')')
01587               n++;
01588            }
01589          else
01590            s++;
01591          break;
01592 
01593        default:
01594          if (TOLOWER (*s) != *n)
01595            return 0;
01596          s++;
01597        }
01598     }
01599   if (*s != ' ' && *s != ',' && *s != '\0')
01600     return 0;
01601   input_line_pointer = s;
01602   return 1;
01603 }
01604 
01605 static char *
01606 tic4x_operand_parse (s, operand)
01607      char *s;
01608      tic4x_operand_t *operand;
01609 {
01610   unsigned int i;
01611   char c;
01612   int ret;
01613   expressionS *exp = &operand->expr;
01614   char *save = input_line_pointer;
01615   char *str;
01616   char *new;
01617   struct hash_entry *entry = NULL;
01618 
01619   input_line_pointer = s;
01620   SKIP_WHITESPACE ();
01621 
01622   str = input_line_pointer;
01623   c = get_symbol_end ();    /* Get terminator.  */
01624   new = input_line_pointer;
01625   if (strlen (str) && (entry = hash_find (tic4x_asg_hash, str)) != NULL)
01626     {
01627       *input_line_pointer = c;
01628       input_line_pointer = (char *) entry;
01629     }
01630   else
01631     {
01632       *input_line_pointer = c;
01633       input_line_pointer = str;
01634     }
01635 
01636   operand->mode = M_UNKNOWN;
01637   switch (*input_line_pointer)
01638     {
01639 #ifdef TIC4X_ALT_SYNTAX
01640     case '%':
01641       input_line_pointer = tic4x_expression (++input_line_pointer, exp);
01642       if (exp->X_op != O_register)
01643        as_bad ("Expecting a register name");
01644       operand->mode = M_REGISTER;
01645       break;
01646 
01647     case '^':
01648       /* Denotes high 16 bits.  */
01649       input_line_pointer = tic4x_expression (++input_line_pointer, exp);
01650       if (exp->X_op == O_constant)
01651        operand->mode = M_IMMED;
01652       else if (exp->X_op == O_big)
01653        {
01654          if (exp->X_add_number)
01655            as_bad ("Number too large");   /* bignum required */
01656          else
01657            {
01658              tic4x_gen_to_words (generic_floating_point_number,
01659                             operand->fwords, S_PRECISION);
01660              operand->mode = M_IMMED_F;
01661            }
01662        }
01663       /* Allow ori ^foo, ar0 to be equivalent to ldi .hi.foo, ar0  */
01664       /* WARNING : The TI C40 assembler cannot do this.  */
01665       else if (exp->X_op == O_symbol)
01666        {
01667          operand->mode = M_HI;
01668          break;
01669        }
01670 
01671     case '#':
01672       input_line_pointer = tic4x_expression (++input_line_pointer, exp);
01673       if (exp->X_op == O_constant)
01674        operand->mode = M_IMMED;
01675       else if (exp->X_op == O_big)
01676        {
01677          if (exp->X_add_number > 0)
01678            as_bad ("Number too large");   /* bignum required.  */
01679          else
01680            {
01681              tic4x_gen_to_words (generic_floating_point_number,
01682                             operand->fwords, S_PRECISION);
01683              operand->mode = M_IMMED_F;
01684            }
01685        }
01686       /* Allow ori foo, ar0 to be equivalent to ldi .lo.foo, ar0  */
01687       /* WARNING : The TI C40 assembler cannot do this.  */
01688       else if (exp->X_op == O_symbol)
01689        {
01690          operand->mode = M_IMMED;
01691          break;
01692        }
01693 
01694       else
01695        as_bad ("Expecting a constant value");
01696       break;
01697     case '\\':
01698 #endif
01699     case '@':
01700       input_line_pointer = tic4x_expression (++input_line_pointer, exp);
01701       if (exp->X_op != O_constant && exp->X_op != O_symbol)
01702        as_bad ("Bad direct addressing construct %s", s);
01703       if (exp->X_op == O_constant)
01704        {
01705          if (exp->X_add_number < 0)
01706            as_bad ("Direct value of %ld is not suitable",
01707                   (long) exp->X_add_number);
01708        }
01709       operand->mode = M_DIRECT;
01710       break;
01711 
01712     case '*':
01713       ret = -1;
01714       for (i = 0; i < tic4x_num_indirects; i++)
01715        if ((ret = tic4x_indirect_parse (operand, &tic4x_indirects[i])))
01716          break;
01717       if (ret < 0)
01718        break;
01719       if (i < tic4x_num_indirects)
01720        {
01721          operand->mode = M_INDIRECT;
01722          /* Indirect addressing mode number.  */
01723          operand->expr.X_add_number = tic4x_indirects[i].modn;
01724          /* Convert *+ARn(0) to *ARn etc.  Maybe we should
01725             squeal about silly ones?  */
01726          if (operand->expr.X_add_number < 0x08 && !operand->disp)
01727            operand->expr.X_add_number = 0x18;
01728        }
01729       else
01730        as_bad ("Unknown indirect addressing mode");
01731       break;
01732 
01733     default:
01734       operand->mode = M_IMMED;     /* Assume immediate.  */
01735       str = input_line_pointer;
01736       input_line_pointer = tic4x_expression (input_line_pointer, exp);
01737       if (exp->X_op == O_register)
01738        {
01739          know (exp->X_add_symbol == 0);
01740          know (exp->X_op_symbol == 0);
01741          operand->mode = M_REGISTER;
01742          break;
01743        }
01744       else if (exp->X_op == O_big)
01745        {
01746          if (exp->X_add_number > 0)
01747            as_bad ("Number too large");   /* bignum required.  */
01748          else
01749            {
01750              tic4x_gen_to_words (generic_floating_point_number,
01751                             operand->fwords, S_PRECISION);
01752              operand->mode = M_IMMED_F;
01753            }
01754          break;
01755        }
01756 #ifdef TIC4X_ALT_SYNTAX
01757       /* Allow ldi foo, ar0 to be equivalent to ldi @foo, ar0.  */
01758       else if (exp->X_op == O_symbol)
01759        {
01760          operand->mode = M_DIRECT;
01761          break;
01762        }
01763 #endif
01764     }
01765   if (entry == NULL)
01766     new = input_line_pointer;
01767   input_line_pointer = save;
01768   return new;
01769 }
01770 
01771 static int 
01772 tic4x_operands_match (inst, insn, check)
01773      tic4x_inst_t *inst;
01774      tic4x_insn_t *insn;
01775      int check;
01776 {
01777   const char *args = inst->args;
01778   unsigned long opcode = inst->opcode;
01779   int num_operands = insn->num_operands;
01780   tic4x_operand_t *operand = insn->operands;
01781   expressionS *exp = &operand->expr;
01782   int ret = 1;
01783   int reg;
01784 
01785   /* Build the opcode, checking as we go to make sure that the
01786      operands match.
01787 
01788      If an operand matches, we modify insn or opcode appropriately,
01789      and do a "continue".  If an operand fails to match, we "break".  */
01790 
01791   insn->nchars = 4;         /* Instructions always 4 bytes.  */
01792   insn->reloc = NO_RELOC;
01793   insn->pcrel = 0;
01794 
01795   if (*args == '\0')
01796     {
01797       insn->opcode = opcode;
01798       return num_operands == 0;
01799     }
01800 
01801   for (;; ++args)
01802     {
01803       switch (*args)
01804        {
01805 
01806        case '\0':           /* End of args.  */
01807          if (num_operands == 1)
01808            {
01809              insn->opcode = opcode;
01810              return ret;
01811            }
01812          break;             /* Too many operands.  */
01813 
01814        case '#':            /* This is only used for ldp.  */
01815          if (operand->mode != M_DIRECT && operand->mode != M_IMMED)
01816            break;
01817          /* While this looks like a direct addressing mode, we actually
01818             use an immediate mode form of ldiu or ldpk instruction.  */
01819          if (exp->X_op == O_constant)
01820            {
01821               if( ( IS_CPU_TIC4X (tic4x_cpu) && exp->X_add_number <= 65535 )
01822                   || ( IS_CPU_TIC3X (tic4x_cpu) && exp->X_add_number <= 255 ) )
01823                 {
01824                   INSERTS (opcode, exp->X_add_number, 15, 0);
01825                   continue;
01826                 }
01827               else
01828                 {
01829                 if (!check)
01830                     as_bad ("Immediate value of %ld is too large for ldf",
01831                             (long) exp->X_add_number);
01832                 ret = -1;
01833                 continue;
01834                 }
01835            }
01836          else if (exp->X_op == O_symbol)
01837            {
01838              insn->reloc = BFD_RELOC_HI16;
01839              insn->exp = *exp;
01840              continue;
01841            }
01842          break;             /* Not direct (dp) addressing.  */
01843 
01844        case '@':            /* direct.  */
01845          if (operand->mode != M_DIRECT)
01846            break;
01847          if (exp->X_op == O_constant)
01848             {
01849               /* Store only the 16 LSBs of the number.  */
01850               INSERTS (opcode, exp->X_add_number, 15, 0);
01851               continue;
01852            }
01853          else if (exp->X_op == O_symbol)
01854            {
01855              insn->reloc = BFD_RELOC_LO16;
01856              insn->exp = *exp;
01857              continue;
01858            }
01859          break;             /* Not direct addressing.  */
01860 
01861        case 'A':
01862          if (operand->mode != M_REGISTER)
01863            break;
01864          reg = exp->X_add_number;
01865          if (reg >= REG_AR0 && reg <= REG_AR7)
01866            INSERTU (opcode, reg - REG_AR0, 24, 22);
01867          else
01868            {
01869               if (!check)
01870                 as_bad ("Destination register must be ARn");
01871              ret = -1;
01872            }
01873          continue;
01874 
01875        case 'B':            /* Unsigned integer immediate.  */
01876          /* Allow br label or br @label.  */
01877          if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
01878            break;
01879          if (exp->X_op == O_constant)
01880            {
01881              if (exp->X_add_number < (1 << 24))
01882               {
01883                 INSERTU (opcode, exp->X_add_number, 23, 0);
01884                 continue;
01885               }
01886              else
01887               {
01888                 if (!check)
01889                     as_bad ("Immediate value of %ld is too large",
01890                             (long) exp->X_add_number);
01891                 ret = -1;
01892                 continue;
01893               }
01894            }
01895          if (IS_CPU_TIC4X (tic4x_cpu))
01896            {
01897              insn->reloc = BFD_RELOC_24_PCREL;
01898              insn->pcrel = 1;
01899            }
01900          else
01901            {
01902              insn->reloc = BFD_RELOC_24;
01903              insn->pcrel = 0;
01904            }
01905          insn->exp = *exp;
01906          continue;
01907 
01908        case 'C':
01909          if (!IS_CPU_TIC4X (tic4x_cpu))
01910            break;
01911          if (operand->mode != M_INDIRECT)
01912            break;
01913          /* Require either *+ARn(disp) or *ARn.  */
01914          if (operand->expr.X_add_number != 0
01915              && operand->expr.X_add_number != 0x18)
01916            {
01917               if (!check)
01918                 as_bad ("Invalid indirect addressing mode");
01919               ret = -1;
01920              continue;
01921            }
01922          INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
01923          INSERTU (opcode, operand->disp, 7, 3);
01924          continue;
01925 
01926        case 'E':
01927          if (!(operand->mode == M_REGISTER))
01928            break;
01929          INSERTU (opcode, exp->X_add_number, 7, 0);
01930          continue;
01931 
01932         case 'e':
01933           if (!(operand->mode == M_REGISTER))
01934             break;
01935          reg = exp->X_add_number;
01936          if ( (reg >= REG_R0 && reg <= REG_R7) 
01937                || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
01938            INSERTU (opcode, reg, 7, 0);
01939          else
01940            {
01941               if (!check)
01942                 as_bad ("Register must be Rn");
01943              ret = -1;
01944            }
01945           continue;
01946 
01947        case 'F':
01948          if (operand->mode != M_IMMED_F
01949              && !(operand->mode == M_IMMED && exp->X_op == O_constant))
01950            break;
01951 
01952          if (operand->mode != M_IMMED_F)
01953            {
01954              /* OK, we 've got something like cmpf 0, r0
01955                 Why can't they stick in a bloody decimal point ?!  */
01956              char string[16];
01957 
01958              /* Create floating point number string.  */
01959              sprintf (string, "%d.0", (int) exp->X_add_number);
01960              tic4x_atof (string, 's', operand->fwords);
01961            }
01962 
01963          INSERTU (opcode, operand->fwords[0], 15, 0);
01964          continue;
01965 
01966        case 'G':
01967          if (operand->mode != M_REGISTER)
01968            break;
01969          INSERTU (opcode, exp->X_add_number, 15, 8);
01970          continue;
01971 
01972         case 'g':
01973          if (operand->mode != M_REGISTER)
01974            break;
01975          reg = exp->X_add_number;
01976          if ( (reg >= REG_R0 && reg <= REG_R7) 
01977                || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
01978            INSERTU (opcode, reg, 15, 8);
01979          else
01980            {
01981               if (!check)
01982                 as_bad ("Register must be Rn");
01983              ret = -1;
01984            }
01985           continue;
01986 
01987        case 'H':
01988          if (operand->mode != M_REGISTER)
01989            break;
01990          reg = exp->X_add_number;
01991          if (reg >= REG_R0 && reg <= REG_R7)
01992            INSERTU (opcode, reg - REG_R0, 18, 16);
01993          else
01994            {
01995               if (!check)
01996                 as_bad ("Register must be R0--R7");
01997              ret = -1;
01998            }
01999          continue;
02000 
02001         case 'i':
02002           if ( operand->mode == M_REGISTER
02003                && tic4x_oplevel & OP_ENH )
02004             {
02005               reg = exp->X_add_number;
02006               INSERTU (opcode, reg, 4, 0);
02007               INSERTU (opcode, 7, 7, 5);
02008               continue;
02009             }
02010           /* Fallthrough */
02011 
02012        case 'I':
02013          if (operand->mode != M_INDIRECT)
02014            break;
02015          if (operand->disp != 0 && operand->disp != 1)
02016            {
02017              if (IS_CPU_TIC4X (tic4x_cpu))
02018               break;
02019               if (!check)
02020                 as_bad ("Invalid indirect addressing mode displacement %d",
02021                         operand->disp);
02022              ret = -1;
02023              continue;
02024            }
02025          INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
02026          INSERTU (opcode, operand->expr.X_add_number, 7, 3);
02027          continue;
02028 
02029         case 'j':
02030           if ( operand->mode == M_REGISTER
02031                && tic4x_oplevel & OP_ENH )
02032             {
02033               reg = exp->X_add_number;
02034               INSERTU (opcode, reg, 12, 8);
02035               INSERTU (opcode, 7, 15, 13);
02036               continue;
02037             }
02038           /* Fallthrough */
02039 
02040        case 'J':
02041          if (operand->mode != M_INDIRECT)
02042            break;
02043          if (operand->disp != 0 && operand->disp != 1)
02044            {
02045              if (IS_CPU_TIC4X (tic4x_cpu))
02046               break;
02047               if (!check)
02048                 as_bad ("Invalid indirect addressing mode displacement %d",
02049                         operand->disp);
02050              ret = -1;
02051              continue;
02052            }
02053          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
02054          INSERTU (opcode, operand->expr.X_add_number, 15, 11);
02055          continue;
02056 
02057        case 'K':
02058          if (operand->mode != M_REGISTER)
02059            break;
02060          reg = exp->X_add_number;
02061          if (reg >= REG_R0 && reg <= REG_R7)
02062            INSERTU (opcode, reg - REG_R0, 21, 19);
02063          else
02064            {
02065               if (!check)
02066                 as_bad ("Register must be R0--R7");
02067              ret = -1;
02068            }
02069          continue;
02070 
02071        case 'L':
02072          if (operand->mode != M_REGISTER)
02073            break;
02074          reg = exp->X_add_number;
02075          if (reg >= REG_R0 && reg <= REG_R7)
02076            INSERTU (opcode, reg - REG_R0, 24, 22);
02077          else
02078            {
02079               if (!check)
02080                 as_bad ("Register must be R0--R7");
02081              ret = -1;
02082            }
02083          continue;
02084 
02085        case 'M':
02086          if (operand->mode != M_REGISTER)
02087            break;
02088          reg = exp->X_add_number;
02089          if (reg == REG_R2 || reg == REG_R3)
02090            INSERTU (opcode, reg - REG_R2, 22, 22);
02091          else
02092            {
02093               if (!check)
02094                 as_bad ("Destination register must be R2 or R3");
02095              ret = -1;
02096            }
02097          continue;
02098 
02099        case 'N':
02100          if (operand->mode != M_REGISTER)
02101            break;
02102          reg = exp->X_add_number;
02103          if (reg == REG_R0 || reg == REG_R1)
02104            INSERTU (opcode, reg - REG_R0, 23, 23);
02105          else
02106            {
02107               if (!check)
02108                 as_bad ("Destination register must be R0 or R1");
02109              ret = -1;
02110            }
02111          continue;
02112 
02113        case 'O':
02114          if (!IS_CPU_TIC4X (tic4x_cpu))
02115            break;
02116          if (operand->mode != M_INDIRECT)
02117            break;
02118          /* Require either *+ARn(disp) or *ARn.  */
02119          if (operand->expr.X_add_number != 0
02120              && operand->expr.X_add_number != 0x18)
02121            {
02122               if (!check)
02123                 as_bad ("Invalid indirect addressing mode");
02124              ret = -1;
02125              continue;
02126            }
02127          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
02128          INSERTU (opcode, operand->disp, 15, 11);
02129          continue;
02130 
02131        case 'P':            /* PC relative displacement.  */
02132          /* Allow br label or br @label.  */
02133          if (operand->mode != M_IMMED && operand->mode != M_DIRECT)
02134            break;
02135          if (exp->X_op == O_constant)
02136            {
02137              if (exp->X_add_number >= -32768 && exp->X_add_number <= 32767)
02138               {
02139                 INSERTS (opcode, exp->X_add_number, 15, 0);
02140                 continue;
02141               }
02142              else
02143               {
02144                   if (!check)
02145                     as_bad ("Displacement value of %ld is too large",
02146                             (long) exp->X_add_number);
02147                 ret = -1;
02148                 continue;
02149               }
02150            }
02151          insn->reloc = BFD_RELOC_16_PCREL;
02152          insn->pcrel = 1;
02153          insn->exp = *exp;
02154          continue;
02155 
02156        case 'Q':
02157          if (operand->mode != M_REGISTER)
02158            break;
02159          reg = exp->X_add_number;
02160          INSERTU (opcode, reg, 15, 0);
02161          continue;
02162 
02163         case 'q':
02164          if (operand->mode != M_REGISTER)
02165            break;
02166          reg = exp->X_add_number;
02167          if ( (reg >= REG_R0 && reg <= REG_R7) 
02168                || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
02169            INSERTU (opcode, reg, 15, 0);
02170          else
02171            {
02172               if (!check)
02173                 as_bad ("Register must be Rn");
02174              ret = -1;
02175            }
02176           continue;
02177 
02178        case 'R':
02179          if (operand->mode != M_REGISTER)
02180            break;
02181          reg = exp->X_add_number;
02182          INSERTU (opcode, reg, 20, 16);
02183          continue;
02184 
02185         case 'r':
02186          if (operand->mode != M_REGISTER)
02187            break;
02188          reg = exp->X_add_number;
02189          if ( (reg >= REG_R0 && reg <= REG_R7) 
02190                || (IS_CPU_TIC4X (tic4x_cpu) && reg >= REG_R8 && reg <= REG_R11) )
02191            INSERTU (opcode, reg, 20, 16);
02192          else
02193            {
02194               if (!check)
02195                 as_bad ("Register must be Rn");
02196              ret = -1;
02197            }
02198           continue;
02199 
02200        case 'S':            /* Short immediate int.  */
02201          if (operand->mode != M_IMMED && operand->mode != M_HI)
02202            break;
02203          if (exp->X_op == O_big)
02204            {
02205               if (!check)
02206                 as_bad ("Floating point number not valid in expression");
02207              ret = -1;
02208              continue;
02209            }
02210          if (exp->X_op == O_constant)
02211            {
02212              if (exp->X_add_number >= -32768 && exp->X_add_number <= 65535)
02213               {
02214                 INSERTS (opcode, exp->X_add_number, 15, 0);
02215                 continue;
02216               }
02217              else
02218               {
02219                 if (!check)
02220                     as_bad ("Signed immediate value %ld too large",
02221                             (long) exp->X_add_number);
02222                 ret = -1;
02223                 continue;
02224               }
02225            }
02226          else if (exp->X_op == O_symbol)
02227            {
02228              if (operand->mode == M_HI)
02229               {
02230                 insn->reloc = BFD_RELOC_HI16;
02231               }
02232              else
02233               {
02234                 insn->reloc = BFD_RELOC_LO16;
02235               }
02236              insn->exp = *exp;
02237              continue;
02238            }
02239          /* Handle cases like ldi foo - $, ar0  where foo
02240             is a forward reference.  Perhaps we should check
02241             for X_op == O_symbol and disallow things like
02242             ldi foo, ar0.  */
02243          insn->reloc = BFD_RELOC_16;
02244          insn->exp = *exp;
02245          continue;
02246 
02247        case 'T':            /* 5-bit immediate value for tic4x stik.  */
02248          if (!IS_CPU_TIC4X (tic4x_cpu))
02249            break;
02250          if (operand->mode != M_IMMED)
02251            break;
02252          if (exp->X_op == O_constant)
02253            {
02254              if (exp->X_add_number < 16 && exp->X_add_number >= -16)
02255               {
02256                 INSERTS (opcode, exp->X_add_number, 20, 16);
02257                 continue;
02258               }
02259              else
02260               {
02261                   if (!check)
02262                     as_bad ("Immediate value of %ld is too large",
02263                             (long) exp->X_add_number);
02264                 ret = -1;
02265                 continue;
02266               }
02267            }
02268          break;             /* No relocations allowed.  */
02269 
02270        case 'U':            /* Unsigned integer immediate.  */
02271          if (operand->mode != M_IMMED && operand->mode != M_HI)
02272            break;
02273          if (exp->X_op == O_constant)
02274            {
02275              if (exp->X_add_number < (1 << 16) && exp->X_add_number >= 0)
02276               {
02277                 INSERTU (opcode, exp->X_add_number, 15, 0);
02278                 continue;
02279               }
02280              else
02281               {
02282                   if (!check)
02283                     as_bad ("Unsigned immediate value %ld too large",
02284                             (long) exp->X_add_number);
02285                 ret = -1;
02286                 continue;
02287               }
02288            }
02289          else if (exp->X_op == O_symbol)
02290            {
02291              if (operand->mode == M_HI)
02292               insn->reloc = BFD_RELOC_HI16;
02293              else
02294               insn->reloc = BFD_RELOC_LO16;
02295 
02296              insn->exp = *exp;
02297              continue;
02298            }
02299          insn->reloc = BFD_RELOC_16;
02300          insn->exp = *exp;
02301          continue;
02302 
02303        case 'V':            /* Trap numbers (immediate field).  */
02304          if (operand->mode != M_IMMED)
02305            break;
02306          if (exp->X_op == O_constant)
02307            {
02308              if (exp->X_add_number < 512 && IS_CPU_TIC4X (tic4x_cpu))
02309               {
02310                 INSERTU (opcode, exp->X_add_number, 8, 0);
02311                 continue;
02312               }
02313              else if (exp->X_add_number < 32 && IS_CPU_TIC3X (tic4x_cpu))
02314               {
02315                 INSERTU (opcode, exp->X_add_number | 0x20, 4, 0);
02316                 continue;
02317               }
02318              else
02319               {
02320                   if (!check)
02321                     as_bad ("Immediate value of %ld is too large",
02322                             (long) exp->X_add_number);
02323                 ret = -1;
02324                 continue;
02325               }
02326            }
02327          break;             /* No relocations allowed.  */
02328 
02329        case 'W':            /* Short immediate int (0--7).  */
02330          if (!IS_CPU_TIC4X (tic4x_cpu))
02331            break;
02332          if (operand->mode != M_IMMED)
02333            break;
02334          if (exp->X_op == O_big)
02335            {
02336               if (!check)
02337                 as_bad ("Floating point number not valid in expression");
02338              ret = -1;
02339              continue;
02340            }
02341          if (exp->X_op == O_constant)
02342            {
02343              if (exp->X_add_number >= -256 && exp->X_add_number <= 127)
02344               {
02345                 INSERTS (opcode, exp->X_add_number, 7, 0);
02346                 continue;
02347               }
02348              else
02349               {
02350                   if (!check)
02351                     as_bad ("Immediate value %ld too large",
02352                             (long) exp->X_add_number);
02353                 ret = -1;
02354                 continue;
02355               }
02356            }
02357          insn->reloc = BFD_RELOC_16;
02358          insn->exp = *exp;
02359          continue;
02360 
02361        case 'X':            /* Expansion register for tic4x.  */
02362          if (operand->mode != M_REGISTER)
02363            break;
02364          reg = exp->X_add_number;
02365          if (reg >= REG_IVTP && reg <= REG_TVTP)
02366            INSERTU (opcode, reg - REG_IVTP, 4, 0);
02367          else
02368            {
02369               if (!check)
02370                 as_bad ("Register must be ivtp or tvtp");
02371              ret = -1;
02372            }
02373          continue;
02374 
02375        case 'Y':            /* Address register for tic4x lda.  */
02376          if (operand->mode != M_REGISTER)
02377            break;
02378          reg = exp->X_add_number;
02379          if (reg >= REG_AR0 && reg <= REG_SP)
02380            INSERTU (opcode, reg, 20, 16);
02381          else
02382            {
02383               if (!check)
02384                 as_bad ("Register must be address register");
02385              ret = -1;
02386            }
02387          continue;
02388 
02389        case 'Z':            /* Expansion register for tic4x.  */
02390          if (operand->mode != M_REGISTER)
02391            break;
02392          reg = exp->X_add_number;
02393          if (reg >= REG_IVTP && reg <= REG_TVTP)
02394            INSERTU (opcode, reg - REG_IVTP, 20, 16);
02395          else
02396            {
02397               if (!check)
02398                 as_bad ("Register must be ivtp or tvtp");
02399              ret = -1;
02400            }
02401          continue;
02402 
02403        case '*':
02404          if (operand->mode != M_INDIRECT)
02405            break;
02406          INSERTS (opcode, operand->disp, 7, 0);
02407          INSERTU (opcode, operand->aregno - REG_AR0, 10, 8);
02408          INSERTU (opcode, operand->expr.X_add_number, 15, 11);
02409          continue;
02410 
02411        case '|':            /* treat as `,' if have ldi_ldi form.  */
02412          if (insn->parallel)
02413            {
02414              if (--num_operands < 0)
02415               break;        /* Too few operands.  */
02416              operand++;
02417              if (operand->mode != M_PARALLEL)
02418               break;
02419            }
02420          /* Fall through.  */
02421 
02422        case ',':            /* Another operand.  */
02423          if (--num_operands < 0)
02424            break;           /* Too few operands.  */
02425          operand++;
02426          exp = &operand->expr;
02427          continue;
02428 
02429        case ';':            /* Another optional operand.  */
02430          if (num_operands == 1 || operand[1].mode == M_PARALLEL)
02431            continue;
02432          if (--num_operands < 0)
02433            break;           /* Too few operands.  */
02434          operand++;
02435          exp = &operand->expr;
02436          continue;
02437 
02438        default:
02439          BAD_CASE (*args);
02440        }
02441       return 0;
02442     }
02443 }
02444 
02445 static void
02446 tic4x_insn_check (insn)
02447      tic4x_insn_t *insn;
02448 {
02449   
02450   if (!strcmp(insn->name, "lda"))
02451     {
02452       if (insn->num_operands < 2 || insn->num_operands > 2)
02453         as_fatal ("Illegal internal LDA insn definition");
02454 
02455       if ( insn->operands[0].mode == M_REGISTER
02456            && insn->operands[1].mode == M_REGISTER
02457            && insn->operands[0].expr.X_add_number == insn->operands[1].expr.X_add_number )
02458         as_bad ("Source and destination register should not be equal");
02459     }
02460   else if( !strcmp(insn->name, "ldi_ldi")
02461            || !strcmp(insn->name, "ldi1_ldi2")
02462            || !strcmp(insn->name, "ldi2_ldi1")
02463            || !strcmp(insn->name, "ldf_ldf")
02464            || !strcmp(insn->name, "ldf1_ldf2")
02465            || !strcmp(insn->name, "ldf2_ldf1") )
02466     {
02467       if ( insn->num_operands < 4 && insn->num_operands > 5 )
02468         as_fatal ("Illegal internal %s insn definition", insn->name);
02469       
02470       if ( insn->operands[1].mode == M_REGISTER
02471            && insn->operands[insn->num_operands-1].mode == M_REGISTER
02472            && insn->operands[1].expr.X_add_number == insn->operands[insn->num_operands-1].expr.X_add_number )
02473         as_warn ("Equal parallell destination registers, one result will be discarded");
02474     }
02475 }
02476 
02477 static void 
02478 tic4x_insn_output (insn)
02479      tic4x_insn_t *insn;
02480 {
02481   char *dst;
02482 
02483   /* Grab another fragment for opcode.  */
02484   dst = frag_more (insn->nchars);
02485 
02486   /* Put out opcode word as a series of bytes in little endian order.  */
02487   md_number_to_chars (dst, insn->opcode, insn->nchars);
02488 
02489   /* Put out the symbol-dependent stuff.  */
02490   if (insn->reloc != NO_RELOC)
02491     {
02492       /* Where is the offset into the fragment for this instruction.  */
02493       fix_new_exp (frag_now,
02494                  dst - frag_now->fr_literal,     /* where */
02495                  insn->nchars,     /* size */
02496                  &insn->exp,
02497                  insn->pcrel,
02498                  insn->reloc);
02499     }
02500 }
02501 
02502 /* Parse the operands.  */
02503 int 
02504 tic4x_operands_parse (s, operands, num_operands)
02505      char *s;
02506      tic4x_operand_t *operands;
02507      int num_operands;
02508 {
02509   if (!*s)
02510     return num_operands;
02511 
02512   do
02513     s = tic4x_operand_parse (s, &operands[num_operands++]);
02514   while (num_operands < TIC4X_OPERANDS_MAX && *s++ == ',');
02515 
02516   if (num_operands > TIC4X_OPERANDS_MAX)
02517     {
02518       as_bad ("Too many operands scanned");
02519       return -1;
02520     }
02521   return num_operands;
02522 }
02523 
02524 /* Assemble a single instruction.  Its label has already been handled
02525    by the generic front end.  We just parse mnemonic and operands, and
02526    produce the bytes of data and relocation.  */
02527 void 
02528 md_assemble (str)
02529      char *str;
02530 {
02531   int ok = 0;
02532   char *s;
02533   int i;
02534   int parsed = 0;
02535   tic4x_inst_t *inst;              /* Instruction template.  */
02536   tic4x_inst_t *first_inst;
02537 
02538   /* Scan for parallel operators */
02539   if (str)
02540     {
02541       s = str;
02542       while (*s && *s != '|')
02543         s++;
02544       
02545       if (*s && s[1]=='|')
02546         {
02547           if(insn->parallel)
02548             {
02549               as_bad ("Parallel opcode cannot contain more than two instructions");
02550               insn->parallel = 0;
02551               insn->in_use = 0;
02552               return;
02553             }
02554           
02555           /* Lets take care of the first part of the parallel insn */
02556           *s++ = 0;
02557           md_assemble(str);
02558           insn->parallel = 1;
02559           str = ++s;
02560           /* .. and let the second run though here */
02561         }
02562     }
02563   
02564   if (str && insn->parallel)
02565     {
02566       /* Find mnemonic (second part of parallel instruction).  */
02567       s = str;
02568       /* Skip past instruction mnemonic.  */
02569       while (*s && *s != ' ')
02570        s++;
02571       if (*s)               /* Null terminate for hash_find.  */
02572        *s++ = '\0';         /* and skip past null.  */
02573       strcat (insn->name, "_");
02574       strncat (insn->name, str, TIC4X_NAME_MAX - strlen (insn->name));
02575 
02576       insn->operands[insn->num_operands++].mode = M_PARALLEL;
02577 
02578       if ((i = tic4x_operands_parse
02579           (s, insn->operands, insn->num_operands)) < 0)
02580        {
02581          insn->parallel = 0;
02582          insn->in_use = 0;
02583          return;
02584        }
02585       insn->num_operands = i;
02586       parsed = 1;
02587     }
02588 
02589   if (insn->in_use)
02590     {
02591       if ((insn->inst = (struct tic4x_inst *)
02592           hash_find (tic4x_op_hash, insn->name)) == NULL)
02593        {
02594          as_bad ("Unknown opcode `%s'.", insn->name);
02595          insn->parallel = 0;
02596          insn->in_use = 0;
02597          return;
02598        }
02599 
02600       inst = insn->inst;
02601       first_inst = NULL;
02602       do
02603         {
02604           ok = tic4x_operands_match (inst, insn, 1);
02605           if (ok < 0)
02606             {
02607               if (!first_inst)
02608                 first_inst = inst;
02609               ok = 0;
02610             }
02611       } while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
02612 
02613       if (ok > 0)
02614         {
02615           tic4x_insn_check (insn);
02616           tic4x_insn_output (insn);
02617         }
02618       else if (!ok)
02619         {
02620           if (first_inst)
02621             tic4x_operands_match (first_inst, insn, 0);
02622           as_bad ("Invalid operands for %s", insn->name);
02623         }
02624       else
02625        as_bad ("Invalid instruction %s", insn->name);
02626     }
02627 
02628   if (str && !parsed)
02629     {
02630       /* Find mnemonic.  */
02631       s = str;
02632       while (*s && *s != ' ')      /* Skip past instruction mnemonic.  */
02633        s++;
02634       if (*s)               /* Null terminate for hash_find.  */
02635        *s++ = '\0';         /* and skip past null.  */
02636       strncpy (insn->name, str, TIC4X_NAME_MAX - 3);
02637 
02638       if ((i = tic4x_operands_parse (s, insn->operands, 0)) < 0)
02639        {
02640          insn->inst = NULL; /* Flag that error occurred.  */
02641          insn->parallel = 0;
02642          insn->in_use = 0;
02643          return;
02644        }
02645       insn->num_operands = i;
02646       insn->in_use = 1;
02647     }
02648   else
02649     insn->in_use = 0;
02650   insn->parallel = 0;
02651 }
02652 
02653 void
02654 tic4x_cleanup ()
02655 {
02656   if (insn->in_use)
02657     md_assemble (NULL);
02658 }
02659 
02660 /* Turn a string in input_line_pointer into a floating point constant
02661    of type type, and store the appropriate bytes in *litP.  The number
02662    of LITTLENUMS emitted is stored in *sizeP.  An error message is
02663    returned, or NULL on OK.  */
02664 
02665 char *
02666 md_atof (type, litP, sizeP)
02667      int type;
02668      char *litP;
02669      int *sizeP;
02670 {
02671   int prec;
02672   int ieee;
02673   LITTLENUM_TYPE words[MAX_LITTLENUMS];
02674   LITTLENUM_TYPE *wordP;
02675   char *t;
02676 
02677   switch (type)
02678     {
02679     case 's':               /* .single */
02680     case 'S':
02681       ieee = 0;
02682       prec = 1;
02683       break;
02684 
02685     case 'd':               /* .double */
02686     case 'D':
02687     case 'f':               /* .float or .single */
02688     case 'F':
02689       ieee = 0;
02690       prec = 2;                    /* 1 32-bit word */
02691       break;
02692 
02693     case 'i':               /* .ieee */
02694     case 'I':
02695       prec = 2;
02696       ieee = 1;
02697       type = 'f';  /* Rewrite type to be usable by atof_ieee() */
02698       break;
02699 
02700     case 'e':               /* .ldouble */
02701     case 'E':
02702       prec = 4;                    /* 2 32-bit words */
02703       ieee = 0;
02704       break;
02705 
02706     default:
02707       *sizeP = 0;
02708       return "Bad call to md_atof()";
02709     }
02710 
02711   if (ieee)
02712     t = atof_ieee (input_line_pointer, type, words);
02713   else
02714     t = tic4x_atof (input_line_pointer, type, words);
02715   if (t)
02716     input_line_pointer = t;
02717   *sizeP = prec * sizeof (LITTLENUM_TYPE);
02718 
02719   /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
02720      little endian byte order.  */
02721   /* SES: However it is required to put the words (32-bits) out in the
02722      correct order, hence we write 2 and 2 littlenums in little endian
02723      order, while we keep the original order on successive words. */
02724   for(wordP = words; wordP<(words+prec) ; wordP+=2)
02725     {
02726       if (wordP<(words+prec-1)) /* Dump wordP[1] (if we have one) */
02727         {
02728           md_number_to_chars (litP, (valueT) (wordP[1]),
02729                               sizeof (LITTLENUM_TYPE));
02730           litP += sizeof (LITTLENUM_TYPE);
02731         }
02732 
02733       /* Dump wordP[0] */
02734       md_number_to_chars (litP, (valueT) (wordP[0]),
02735                           sizeof (LITTLENUM_TYPE));
02736       litP += sizeof (LITTLENUM_TYPE);
02737     }
02738   return 0;
02739 }
02740 
02741 void 
02742 md_apply_fix (fixP, value, seg)
02743      fixS *fixP;
02744      valueT *value;
02745      segT seg ATTRIBUTE_UNUSED;
02746 {
02747   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
02748   valueT val = *value;
02749 
02750   switch (fixP->fx_r_type)
02751     {
02752     case BFD_RELOC_HI16:
02753       val >>= 16;
02754       break;
02755 
02756     case BFD_RELOC_LO16:
02757       val &= 0xffff;
02758       break;
02759     default:
02760       break;
02761     }
02762 
02763   switch (fixP->fx_r_type)
02764     {
02765     case BFD_RELOC_32:
02766       buf[3] = val >> 24;
02767     case BFD_RELOC_24:
02768     case BFD_RELOC_24_PCREL:
02769       buf[2] = val >> 16;
02770     case BFD_RELOC_16:
02771     case BFD_RELOC_16_PCREL:
02772     case BFD_RELOC_LO16:
02773     case BFD_RELOC_HI16:
02774       buf[1] = val >> 8;
02775       buf[0] = val;
02776       break;
02777 
02778     case NO_RELOC:
02779     default:
02780       as_bad ("Bad relocation type: 0x%02x", fixP->fx_r_type);
02781       break;
02782     }
02783 
02784   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) fixP->fx_done = 1;
02785 }
02786 
02787 /* Should never be called for tic4x.  */
02788 void 
02789 md_convert_frag (headers, sec, fragP)
02790      bfd *headers ATTRIBUTE_UNUSED;
02791      segT sec ATTRIBUTE_UNUSED;
02792      fragS *fragP ATTRIBUTE_UNUSED;
02793 {
02794   as_fatal ("md_convert_frag");
02795 }
02796 
02797 /* Should never be called for tic4x.  */
02798 void
02799 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
02800      char *ptr ATTRIBUTE_UNUSED;
02801      addressT from_addr ATTRIBUTE_UNUSED;
02802      addressT to_addr ATTRIBUTE_UNUSED;
02803      fragS *frag ATTRIBUTE_UNUSED;
02804      symbolS *to_symbol ATTRIBUTE_UNUSED;
02805 {
02806   as_fatal ("md_create_short_jmp\n");
02807 }
02808 
02809 /* Should never be called for tic4x.  */
02810 void
02811 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
02812      char *ptr ATTRIBUTE_UNUSED;
02813      addressT from_addr ATTRIBUTE_UNUSED;
02814      addressT to_addr ATTRIBUTE_UNUSED;
02815      fragS *frag ATTRIBUTE_UNUSED;
02816      symbolS *to_symbol ATTRIBUTE_UNUSED;
02817 {
02818   as_fatal ("md_create_long_jump\n");
02819 }
02820 
02821 /* Should never be called for tic4x.  */
02822 int
02823 md_estimate_size_before_relax (fragP, segtype)
02824      register fragS *fragP ATTRIBUTE_UNUSED;
02825      segT segtype ATTRIBUTE_UNUSED;
02826 {
02827   as_fatal ("md_estimate_size_before_relax\n");
02828   return 0;
02829 }
02830 
02831 
02832 int
02833 md_parse_option (c, arg)
02834      int c;
02835      char *arg;
02836 {
02837   switch (c)
02838     {
02839     case OPTION_CPU:             /* cpu brand */
02840       if (TOLOWER (*arg) == 'c')
02841        arg++;
02842       tic4x_cpu = atoi (arg);
02843       if (!IS_CPU_TIC3X (tic4x_cpu) && !IS_CPU_TIC4X (tic4x_cpu))
02844        as_warn ("Unsupported processor generation %d", tic4x_cpu);
02845       break;
02846 
02847     case OPTION_REV:             /* cpu revision */
02848       tic4x_revision = atoi (arg);
02849       break;
02850 
02851     case 'b':
02852       as_warn ("Option -b is depreciated, please use -mbig");
02853     case OPTION_BIG:             /* big model */
02854       tic4x_big_model = 1;
02855       break;
02856 
02857     case 'p':
02858       as_warn ("Option -p is depreciated, please use -mmemparm");
02859     case OPTION_MEMPARM:         /* push args */
02860       tic4x_reg_args = 0;
02861       break;
02862 
02863     case 'r':               
02864       as_warn ("Option -r is depreciated, please use -mregparm");
02865     case OPTION_REGPARM:        /* register args */
02866       tic4x_reg_args = 1;
02867       break;
02868 
02869     case 's':
02870       as_warn ("Option -s is depreciated, please use -msmall");
02871     case OPTION_SMALL:             /* small model */
02872       tic4x_big_model = 0;
02873       break;
02874 
02875     case OPTION_IDLE2:
02876       tic4x_idle2 = 1;
02877       break;
02878 
02879     case OPTION_LOWPOWER:
02880       tic4x_lowpower = 1;
02881       break;
02882 
02883     case OPTION_ENHANCED:
02884       tic4x_enhanced = 1;
02885       break;
02886 
02887     default:
02888       return 0;
02889     }
02890 
02891   return 1;
02892 }
02893 
02894 void
02895 md_show_usage (stream)
02896      FILE *stream;
02897 {
02898   fprintf (stream,
02899       _("\nTIC4X options:\n"
02900        "  -mcpu=CPU  -mCPU        select architecture variant. CPU can be:\n"
02901        "                            30 - TMS320C30\n"
02902        "                            31 - TMS320C31, TMS320LC31\n"
02903        "                            32 - TMS320C32\n"
02904         "                            33 - TMS320VC33\n"
02905        "                            40 - TMS320C40\n"
02906        "                            44 - TMS320C44\n"
02907         "  -mrev=REV               set cpu hardware revision (integer numbers).\n"
02908         "                          Combinations of -mcpu and -mrev will enable/disable\n"
02909         "                          the appropriate options (-midle2, -mlowpower and\n"
02910         "                          -menhanced) according to the selected type\n"
02911         "  -mbig                   select big memory model\n"
02912         "  -msmall                 select small memory model (default)\n"
02913         "  -mregparm               select register parameters (default)\n"
02914         "  -mmemparm               select memory parameters\n"
02915         "  -midle2                 enable IDLE2 support\n"
02916         "  -mlowpower              enable LOPOWER and MAXSPEED support\n"
02917         "  -menhanced              enable enhanced opcode support\n"));
02918 }
02919 
02920 /* This is called when a line is unrecognized.  This is used to handle
02921    definitions of TI C3x tools style local labels $n where n is a single
02922    decimal digit.  */
02923 int 
02924 tic4x_unrecognized_line (c)
02925      int c;
02926 {
02927   int lab;
02928   char *s;
02929 
02930   if (c != '$' || ! ISDIGIT (input_line_pointer[0]))
02931     return 0;
02932 
02933   s = input_line_pointer;
02934 
02935   /* Let's allow multiple digit local labels.  */
02936   lab = 0;
02937   while (ISDIGIT (*s))
02938     {
02939       lab = lab * 10 + *s - '0';
02940       s++;
02941     }
02942 
02943   if (dollar_label_defined (lab))
02944     {
02945       as_bad ("Label \"$%d\" redefined", lab);
02946       return 0;
02947     }
02948 
02949   define_dollar_label (lab);
02950   colon (dollar_label_name (lab, 0));
02951   input_line_pointer = s + 1;
02952 
02953   return 1;
02954 }
02955 
02956 /* Handle local labels peculiar to us referred to in an expression.  */
02957 symbolS *
02958 md_undefined_symbol (name)
02959      char *name;
02960 {
02961   /* Look for local labels of the form $n.  */
02962   if (name[0] == '$' && ISDIGIT (name[1]))
02963     {
02964       symbolS *symbolP;
02965       char *s = name + 1;
02966       int lab = 0;
02967 
02968       while (ISDIGIT ((unsigned char) *s))
02969        {
02970          lab = lab * 10 + *s - '0';
02971          s++;
02972        }
02973       if (dollar_label_defined (lab))
02974        {
02975          name = dollar_label_name (lab, 0);
02976          symbolP = symbol_find (name);
02977        }
02978       else
02979        {
02980          name = dollar_label_name (lab, 1);
02981          symbolP = symbol_find_or_make (name);
02982        }
02983 
02984       return symbolP;
02985     }
02986   return NULL;
02987 }
02988 
02989 /* Parse an operand that is machine-specific.  */
02990 void
02991 md_operand (expressionP)
02992      expressionS *expressionP ATTRIBUTE_UNUSED;
02993 {
02994 }
02995 
02996 /* Round up a section size to the appropriate boundary---do we need this?  */
02997 valueT
02998 md_section_align (segment, size)
02999      segT segment ATTRIBUTE_UNUSED;
03000      valueT size;
03001 {
03002   return size;                     /* Byte (i.e., 32-bit) alignment is fine?  */
03003 }
03004 
03005 static int 
03006 tic4x_pc_offset (op)
03007      unsigned int op;
03008 {
03009   /* Determine the PC offset for a C[34]x instruction.
03010      This could be simplified using some boolean algebra
03011      but at the expense of readability.  */
03012   switch (op >> 24)
03013     {
03014     case 0x60:                     /* br */
03015     case 0x62:                     /* call  (C4x) */
03016     case 0x64:                     /* rptb  (C4x) */
03017       return 1;
03018     case 0x61:                     /* brd */
03019     case 0x63:                     /* laj */
03020     case 0x65:                     /* rptbd (C4x) */
03021       return 3;
03022     case 0x66:                     /* swi */
03023     case 0x67:
03024       return 0;
03025     default:
03026       break;
03027     }
03028 
03029   switch ((op & 0xffe00000) >> 20)
03030     {
03031     case 0x6a0:             /* bB */
03032     case 0x720:             /* callB */
03033     case 0x740:             /* trapB */
03034       return 1;
03035 
03036     case 0x6a2:             /* bBd */
03037     case 0x6a6:             /* bBat */
03038     case 0x6aa:             /* bBaf */
03039     case 0x722:             /* lajB */
03040     case 0x748:             /* latB */
03041     case 0x798:             /* rptbd */
03042       return 3;
03043 
03044     default:
03045       break;
03046     }
03047 
03048   switch ((op & 0xfe200000) >> 20)
03049     {
03050     case 0x6e0:             /* dbB */
03051       return 1;
03052 
03053     case 0x6e2:             /* dbBd */
03054       return 3;
03055 
03056     default:
03057       break;
03058     }
03059 
03060   return 0;
03061 }
03062 
03063 /* Exactly what point is a PC-relative offset relative TO?
03064    With the C3x we have the following:
03065    DBcond,  Bcond   disp + PC + 1 => PC
03066    DBcondD, BcondD  disp + PC + 3 => PC
03067  */
03068 long
03069 md_pcrel_from (fixP)
03070      fixS *fixP;
03071 {
03072   unsigned char *buf;
03073   unsigned int op;
03074 
03075   buf = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
03076   op = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
03077 
03078   return ((fixP->fx_where + fixP->fx_frag->fr_address) >> 2) +
03079     tic4x_pc_offset (op);
03080 }
03081 
03082 /* Fill the alignment area with NOP's on .text, unless fill-data
03083    was specified. */
03084 int 
03085 tic4x_do_align (alignment, fill, len, max)
03086      int alignment ATTRIBUTE_UNUSED;
03087      const char *fill ATTRIBUTE_UNUSED;
03088      int len ATTRIBUTE_UNUSED;
03089      int max ATTRIBUTE_UNUSED;
03090 {
03091   unsigned long nop = TIC_NOP_OPCODE;
03092 
03093   /* Because we are talking lwords, not bytes, adjust alignment to do words */
03094   alignment += 2;
03095   
03096   if (alignment != 0 && !need_pass_2)
03097     {
03098       if (fill == NULL)
03099         {
03100           /*if (subseg_text_p (now_seg))*/  /* FIXME: doesn't work for .text for some reason */
03101           frag_align_pattern( alignment, (const char *)&nop, sizeof(nop), max);
03102           return 1;
03103           /*else
03104             frag_align (alignment, 0, max);*/
03105        }
03106       else if (len <= 1)
03107        frag_align (alignment, *fill, max);
03108       else
03109        frag_align_pattern (alignment, fill, len, max);
03110     }
03111   
03112   /* Return 1 to skip the default alignment function */
03113   return 1;
03114 }
03115 
03116 /* Look for and remove parallel instruction operator ||.  */
03117 void 
03118 tic4x_start_line ()
03119 {
03120   char *s = input_line_pointer;
03121 
03122   SKIP_WHITESPACE ();
03123 
03124   /* If parallel instruction prefix found at start of line, skip it.  */
03125   if (*input_line_pointer == '|' && input_line_pointer[1] == '|')
03126     {
03127       if (insn->in_use)
03128        {
03129          insn->parallel = 1;
03130          input_line_pointer ++;
03131           *input_line_pointer = ' ';
03132          /* So line counters get bumped.  */
03133          input_line_pointer[-1] = '\n';
03134        }
03135     }
03136   else
03137     {
03138       /* Write out the previous insn here */
03139       if (insn->in_use)
03140        md_assemble (NULL);
03141       input_line_pointer = s;
03142     }
03143 }
03144 
03145 arelent *
03146 tc_gen_reloc (seg, fixP)
03147      asection *seg ATTRIBUTE_UNUSED;
03148      fixS *fixP;
03149 {
03150   arelent *reloc;
03151 
03152   reloc = (arelent *) xmalloc (sizeof (arelent));
03153 
03154   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
03155   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
03156   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
03157   reloc->address /= OCTETS_PER_BYTE;
03158   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
03159   if (reloc->howto == (reloc_howto_type *) NULL)
03160     {
03161       as_bad_where (fixP->fx_file, fixP->fx_line,
03162                   "Reloc %d not supported by object file format",
03163                   (int) fixP->fx_r_type);
03164       return NULL;
03165     }
03166 
03167   if (fixP->fx_r_type == BFD_RELOC_HI16)
03168     reloc->addend = fixP->fx_offset;
03169   else
03170     reloc->addend = fixP->fx_addnumber;
03171 
03172   return reloc;
03173 }