Back to index

cell-binutils  2.17cvs20070401
tc-bfin.c
Go to the documentation of this file.
00001 /* tc-bfin.c -- Assembler for the ADI Blackfin.
00002    Copyright 2005, 2006
00003    Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "struc-symbol.h"
00024 #include "bfin-defs.h"
00025 #include "obstack.h"
00026 #include "safe-ctype.h"
00027 #ifdef OBJ_ELF
00028 #include "dwarf2dbg.h"
00029 #endif
00030 #include "libbfd.h"
00031 #include "elf/common.h"
00032 #include "elf/bfin.h"
00033 
00034 extern int yyparse (void);
00035 struct yy_buffer_state;
00036 typedef struct yy_buffer_state *YY_BUFFER_STATE;
00037 extern YY_BUFFER_STATE yy_scan_string (const char *yy_str);
00038 extern void yy_delete_buffer (YY_BUFFER_STATE b);
00039 static parse_state parse (char *line);
00040 static void bfin_s_bss PARAMS ((int));
00041 static int md_chars_to_number PARAMS ((char *, int));
00042 
00043 /* Global variables. */
00044 struct bfin_insn *insn;
00045 int last_insn_size;
00046 
00047 extern struct obstack mempool;
00048 FILE *errorf;
00049 
00050 /* Flags to set in the elf header */
00051 #define DEFAULT_FLAGS 0
00052 
00053 static flagword bfin_flags = DEFAULT_FLAGS;
00054 static const char *bfin_pic_flag = (const char *)0;
00055 
00056 /* Registers list.  */
00057 struct bfin_reg_entry
00058 {
00059   const char *name;
00060   int number;
00061 };
00062 
00063 static const struct bfin_reg_entry bfin_reg_info[] = {
00064   {"R0.L", REG_RL0},
00065   {"R1.L", REG_RL1},
00066   {"R2.L", REG_RL2},
00067   {"R3.L", REG_RL3},
00068   {"R4.L", REG_RL4},
00069   {"R5.L", REG_RL5},
00070   {"R6.L", REG_RL6},
00071   {"R7.L", REG_RL7},
00072   {"R0.H", REG_RH0},
00073   {"R1.H", REG_RH1},
00074   {"R2.H", REG_RH2},
00075   {"R3.H", REG_RH3},
00076   {"R4.H", REG_RH4},
00077   {"R5.H", REG_RH5},
00078   {"R6.H", REG_RH6},
00079   {"R7.H", REG_RH7},
00080   {"R0", REG_R0},
00081   {"R1", REG_R1},
00082   {"R2", REG_R2},
00083   {"R3", REG_R3},
00084   {"R4", REG_R4},
00085   {"R5", REG_R5},
00086   {"R6", REG_R6},
00087   {"R7", REG_R7},
00088   {"P0", REG_P0},
00089   {"P0.H", REG_P0},
00090   {"P0.L", REG_P0},
00091   {"P1", REG_P1},
00092   {"P1.H", REG_P1},
00093   {"P1.L", REG_P1},
00094   {"P2", REG_P2},
00095   {"P2.H", REG_P2},
00096   {"P2.L", REG_P2},
00097   {"P3", REG_P3},
00098   {"P3.H", REG_P3},
00099   {"P3.L", REG_P3},
00100   {"P4", REG_P4},
00101   {"P4.H", REG_P4},
00102   {"P4.L", REG_P4},
00103   {"P5", REG_P5},
00104   {"P5.H", REG_P5},
00105   {"P5.L", REG_P5},
00106   {"SP", REG_SP},
00107   {"SP.L", REG_SP},
00108   {"SP.H", REG_SP},
00109   {"FP", REG_FP},
00110   {"FP.L", REG_FP},
00111   {"FP.H", REG_FP},
00112   {"A0x", REG_A0x},
00113   {"A1x", REG_A1x},
00114   {"A0w", REG_A0w},
00115   {"A1w", REG_A1w},
00116   {"A0.x", REG_A0x},
00117   {"A1.x", REG_A1x},
00118   {"A0.w", REG_A0w},
00119   {"A1.w", REG_A1w},
00120   {"A0", REG_A0},
00121   {"A0.L", REG_A0},
00122   {"A0.H", REG_A0},
00123   {"A1", REG_A1},
00124   {"A1.L", REG_A1},
00125   {"A1.H", REG_A1},
00126   {"I0", REG_I0},
00127   {"I0.L", REG_I0},
00128   {"I0.H", REG_I0},
00129   {"I1", REG_I1},
00130   {"I1.L", REG_I1},
00131   {"I1.H", REG_I1},
00132   {"I2", REG_I2},
00133   {"I2.L", REG_I2},
00134   {"I2.H", REG_I2},
00135   {"I3", REG_I3},
00136   {"I3.L", REG_I3},
00137   {"I3.H", REG_I3},
00138   {"M0", REG_M0},
00139   {"M0.H", REG_M0},
00140   {"M0.L", REG_M0},
00141   {"M1", REG_M1},
00142   {"M1.H", REG_M1},
00143   {"M1.L", REG_M1},
00144   {"M2", REG_M2},
00145   {"M2.H", REG_M2},
00146   {"M2.L", REG_M2},
00147   {"M3", REG_M3},
00148   {"M3.H", REG_M3},
00149   {"M3.L", REG_M3},
00150   {"B0", REG_B0},
00151   {"B0.H", REG_B0},
00152   {"B0.L", REG_B0},
00153   {"B1", REG_B1},
00154   {"B1.H", REG_B1},
00155   {"B1.L", REG_B1},
00156   {"B2", REG_B2},
00157   {"B2.H", REG_B2},
00158   {"B2.L", REG_B2},
00159   {"B3", REG_B3},
00160   {"B3.H", REG_B3},
00161   {"B3.L", REG_B3},
00162   {"L0", REG_L0},
00163   {"L0.H", REG_L0},
00164   {"L0.L", REG_L0},
00165   {"L1", REG_L1},
00166   {"L1.H", REG_L1},
00167   {"L1.L", REG_L1},
00168   {"L2", REG_L2},
00169   {"L2.H", REG_L2},
00170   {"L2.L", REG_L2},
00171   {"L3", REG_L3},
00172   {"L3.H", REG_L3},
00173   {"L3.L", REG_L3},
00174   {"AZ", S_AZ},
00175   {"AN", S_AN},
00176   {"AC0", S_AC0},
00177   {"AC1", S_AC1},
00178   {"AV0", S_AV0},
00179   {"AV0S", S_AV0S},
00180   {"AV1", S_AV1},
00181   {"AV1S", S_AV1S},
00182   {"AQ", S_AQ},
00183   {"V", S_V},
00184   {"VS", S_VS},
00185   {"sftreset", REG_sftreset},
00186   {"omode", REG_omode},
00187   {"excause", REG_excause},
00188   {"emucause", REG_emucause},
00189   {"idle_req", REG_idle_req},
00190   {"hwerrcause", REG_hwerrcause},
00191   {"CC", REG_CC},
00192   {"LC0", REG_LC0},
00193   {"LC1", REG_LC1},
00194   {"ASTAT", REG_ASTAT},
00195   {"RETS", REG_RETS},
00196   {"LT0", REG_LT0},
00197   {"LB0", REG_LB0},
00198   {"LT1", REG_LT1},
00199   {"LB1", REG_LB1},
00200   {"CYCLES", REG_CYCLES},
00201   {"CYCLES2", REG_CYCLES2},
00202   {"USP", REG_USP},
00203   {"SEQSTAT", REG_SEQSTAT},
00204   {"SYSCFG", REG_SYSCFG},
00205   {"RETI", REG_RETI},
00206   {"RETX", REG_RETX},
00207   {"RETN", REG_RETN},
00208   {"RETE", REG_RETE},
00209   {"EMUDAT", REG_EMUDAT},
00210   {0, 0}
00211 };
00212 
00213 /* Blackfin specific function to handle FD-PIC pointer initializations.  */
00214 
00215 static void
00216 bfin_pic_ptr (int nbytes)
00217 {
00218   expressionS exp;
00219   char *p;
00220 
00221   if (nbytes != 4)
00222     abort ();
00223 
00224 #ifdef md_flush_pending_output
00225   md_flush_pending_output ();
00226 #endif
00227 
00228   if (is_it_end_of_statement ())
00229     {
00230       demand_empty_rest_of_line ();
00231       return;
00232     }
00233 
00234 #ifdef md_cons_align
00235   md_cons_align (nbytes);
00236 #endif
00237 
00238   do
00239     {
00240       bfd_reloc_code_real_type reloc_type = BFD_RELOC_BFIN_FUNCDESC;
00241       
00242       if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
00243        {
00244          input_line_pointer += 9;
00245          expression (&exp);
00246          if (*input_line_pointer == ')')
00247            input_line_pointer++;
00248          else
00249            as_bad ("missing ')'");
00250        }
00251       else
00252        error ("missing funcdesc in picptr");
00253 
00254       p = frag_more (4);
00255       memset (p, 0, 4);
00256       fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
00257                  reloc_type);
00258     }
00259   while (*input_line_pointer++ == ',');
00260 
00261   input_line_pointer--;                   /* Put terminator back into stream. */
00262   demand_empty_rest_of_line ();
00263 }
00264 
00265 static void
00266 bfin_s_bss (int ignore ATTRIBUTE_UNUSED)
00267 {
00268   register int temp;
00269 
00270   temp = get_absolute_expression ();
00271   subseg_set (bss_section, (subsegT) temp);
00272   demand_empty_rest_of_line ();
00273 }
00274 
00275 const pseudo_typeS md_pseudo_table[] = {
00276   {"align", s_align_bytes, 0},
00277   {"byte2", cons, 2},
00278   {"byte4", cons, 4},
00279   {"picptr", bfin_pic_ptr, 4},
00280   {"code", obj_elf_section, 0},
00281   {"db", cons, 1},
00282   {"dd", cons, 4},
00283   {"dw", cons, 2},
00284   {"p", s_ignore, 0},
00285   {"pdata", s_ignore, 0},
00286   {"var", s_ignore, 0},
00287   {"bss", bfin_s_bss, 0},
00288   {0, 0, 0}
00289 };
00290 
00291 /* Characters that are used to denote comments and line separators. */
00292 const char comment_chars[] = "";
00293 const char line_comment_chars[] = "#";
00294 const char line_separator_chars[] = ";";
00295 
00296 /* Characters that can be used to separate the mantissa from the
00297    exponent in floating point numbers. */
00298 const char EXP_CHARS[] = "eE";
00299 
00300 /* Characters that mean this number is a floating point constant.
00301    As in 0f12.456 or  0d1.2345e12.  */
00302 const char FLT_CHARS[] = "fFdDxX";
00303 
00304 /* Define bfin-specific command-line options (there are none). */
00305 const char *md_shortopts = "";
00306 
00307 #define OPTION_FDPIC        (OPTION_MD_BASE)
00308 
00309 struct option md_longopts[] =
00310 {
00311   { "mfdpic",        no_argument,         NULL, OPTION_FDPIC      },
00312   { NULL,            no_argument,         NULL, 0                 },
00313 };
00314 
00315 size_t md_longopts_size = sizeof (md_longopts);
00316 
00317 
00318 int
00319 md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED)
00320 {
00321   switch (c)
00322     {
00323     default:
00324       return 0;
00325 
00326     case OPTION_FDPIC:
00327       bfin_flags |= EF_BFIN_FDPIC;
00328       bfin_pic_flag = "-mfdpic";
00329       break;
00330     }
00331 
00332   return 1;
00333 }
00334 
00335 void
00336 md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
00337 {
00338   fprintf (stream, _(" BFIN specific command line options:\n"));
00339 }
00340 
00341 /* Perform machine-specific initializations.  */
00342 void
00343 md_begin ()
00344 {
00345   /* Set the ELF flags if desired. */
00346   if (bfin_flags)
00347     bfd_set_private_flags (stdoutput, bfin_flags);
00348 
00349   /* Set the default machine type. */
00350   if (!bfd_set_arch_mach (stdoutput, bfd_arch_bfin, 0))
00351     as_warn ("Could not set architecture and machine.");
00352 
00353   /* Ensure that lines can begin with '(', for multiple
00354      register stack pops. */
00355   lex_type ['('] = LEX_BEGIN_NAME;
00356   
00357 #ifdef OBJ_ELF
00358   record_alignment (text_section, 2);
00359   record_alignment (data_section, 2);
00360   record_alignment (bss_section, 2);
00361 #endif
00362 
00363   errorf = stderr;
00364   obstack_init (&mempool);
00365 
00366 #ifdef DEBUG
00367   extern int debug_codeselection;
00368   debug_codeselection = 1;
00369 #endif 
00370 
00371   last_insn_size = 0;
00372 }
00373 
00374 /* Perform the main parsing, and assembly of the input here.  Also,
00375    call the required routines for alignment and fixups here.
00376    This is called for every line that contains real assembly code.  */
00377 
00378 void
00379 md_assemble (char *line)
00380 {
00381   char *toP = 0;
00382   extern char *current_inputline;
00383   int size, insn_size;
00384   struct bfin_insn *tmp_insn;
00385   size_t len;
00386   static size_t buffer_len = 0;
00387   parse_state state;
00388 
00389   len = strlen (line);
00390   if (len + 2 > buffer_len)
00391     {
00392       if (buffer_len > 0)
00393        free (current_inputline);
00394       buffer_len = len + 40;
00395       current_inputline = xmalloc (buffer_len);
00396     }
00397   memcpy (current_inputline, line, len);
00398   current_inputline[len] = ';';
00399   current_inputline[len + 1] = '\0';
00400 
00401   state = parse (current_inputline);
00402   if (state == NO_INSN_GENERATED)
00403     return;
00404 
00405   for (insn_size = 0, tmp_insn = insn; tmp_insn; tmp_insn = tmp_insn->next)
00406     if (!tmp_insn->reloc || !tmp_insn->exp->symbol)
00407       insn_size += 2;
00408 
00409   if (insn_size)
00410     toP = frag_more (insn_size);
00411 
00412   last_insn_size = insn_size;
00413 
00414 #ifdef DEBUG
00415   printf ("INS:");
00416 #endif
00417   while (insn)
00418     {
00419       if (insn->reloc && insn->exp->symbol)
00420        {
00421          char *prev_toP = toP - 2;
00422          switch (insn->reloc)
00423            {
00424            case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
00425            case BFD_RELOC_24_PCREL:
00426            case BFD_RELOC_BFIN_16_LOW:
00427            case BFD_RELOC_BFIN_16_HIGH:
00428              size = 4;
00429              break;
00430            default:
00431              size = 2;
00432            }
00433 
00434          /* Following if condition checks for the arithmetic relocations.
00435             If the case then it doesn't required to generate the code.
00436             It has been assumed that, their ID will be contiguous.  */
00437          if ((BFD_ARELOC_BFIN_PUSH <= insn->reloc
00438                && BFD_ARELOC_BFIN_COMP >= insn->reloc)
00439               || insn->reloc == BFD_RELOC_BFIN_16_IMM)
00440            {
00441              size = 2;
00442            }
00443          if (insn->reloc == BFD_ARELOC_BFIN_CONST
00444               || insn->reloc == BFD_ARELOC_BFIN_PUSH)
00445            size = 4;
00446 
00447          fix_new (frag_now,
00448                    (prev_toP - frag_now->fr_literal),
00449                  size, insn->exp->symbol, insn->exp->value,
00450                    insn->pcrel, insn->reloc);
00451        }
00452       else
00453        {
00454          md_number_to_chars (toP, insn->value, 2);
00455          toP += 2;
00456        }
00457 
00458 #ifdef DEBUG
00459       printf (" reloc :");
00460       printf (" %02x%02x", ((unsigned char *) &insn->value)[0],
00461               ((unsigned char *) &insn->value)[1]);
00462       printf ("\n");
00463 #endif
00464       insn = insn->next;
00465     }
00466 #ifdef OBJ_ELF
00467   dwarf2_emit_insn (insn_size);
00468 #endif
00469 }
00470 
00471 /* Parse one line of instructions, and generate opcode for it.
00472    To parse the line, YACC and LEX are used, because the instruction set
00473    syntax doesn't confirm to the AT&T assembly syntax.
00474    To call a YACC & LEX generated parser, we must provide the input via
00475    a FILE stream, otherwise stdin is used by default.  Below the input
00476    to the function will be put into a temporary file, then the generated
00477    parser uses the temporary file for parsing.  */
00478 
00479 static parse_state
00480 parse (char *line)
00481 {
00482   parse_state state;
00483   YY_BUFFER_STATE buffstate;
00484 
00485   buffstate = yy_scan_string (line);
00486 
00487   /* our lex requires setting the start state to keyword
00488      every line as the first word may be a keyword.
00489      Fixes a bug where we could not have keywords as labels.  */
00490   set_start_state ();
00491 
00492   /* Call yyparse here.  */
00493   state = yyparse ();
00494   if (state == SEMANTIC_ERROR)
00495     {
00496       as_bad ("Parse failed.");
00497       insn = 0;
00498     }
00499 
00500   yy_delete_buffer (buffstate);
00501   return state;
00502 }
00503 
00504 /* We need to handle various expressions properly.
00505    Such as, [SP--] = 34, concerned by md_assemble().  */
00506 
00507 void
00508 md_operand (expressionS * expressionP)
00509 {
00510   if (*input_line_pointer == '[')
00511     {
00512       as_tsktsk ("We found a '['!");
00513       input_line_pointer++;
00514       expression (expressionP);
00515     }
00516 }
00517 
00518 /* Handle undefined symbols. */
00519 symbolS *
00520 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
00521 {
00522   return (symbolS *) 0;
00523 }
00524 
00525 int
00526 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
00527                                segT segment ATTRIBUTE_UNUSED)
00528 {
00529   return 0;
00530 }
00531 
00532 /* Convert from target byte order to host byte order.  */
00533 
00534 static int
00535 md_chars_to_number (char *val, int n)
00536 {
00537   int retval;
00538 
00539   for (retval = 0; n--;)
00540     {
00541       retval <<= 8;
00542       retval |= val[n];
00543     }
00544   return retval;
00545 }
00546 
00547 void
00548 md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
00549 {
00550   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
00551 
00552   long value = *valueP;
00553   long newval;
00554 
00555   switch (fixP->fx_r_type)
00556     {
00557     case BFD_RELOC_BFIN_GOT:
00558     case BFD_RELOC_BFIN_GOT17M4:
00559     case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
00560       fixP->fx_no_overflow = 1;
00561       newval = md_chars_to_number (where, 2);
00562       newval |= 0x0 & 0x7f;
00563       md_number_to_chars (where, newval, 2);
00564       break;
00565 
00566     case BFD_RELOC_BFIN_10_PCREL:
00567       if (!value)
00568        break;
00569       if (value < -1024 || value > 1022)
00570        as_bad_where (fixP->fx_file, fixP->fx_line,
00571                       "pcrel too far BFD_RELOC_BFIN_10");
00572 
00573       /* 11 bit offset even numbered, so we remove right bit.  */
00574       value = value >> 1;
00575       newval = md_chars_to_number (where, 2);
00576       newval |= value & 0x03ff;
00577       md_number_to_chars (where, newval, 2);
00578       break;
00579 
00580     case BFD_RELOC_BFIN_12_PCREL_JUMP:
00581     case BFD_RELOC_BFIN_12_PCREL_JUMP_S:
00582     case BFD_RELOC_12_PCREL:
00583       if (!value)
00584        break;
00585 
00586       if (value < -4096 || value > 4094)
00587        as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_12");
00588       /* 13 bit offset even numbered, so we remove right bit.  */
00589       value = value >> 1;
00590       newval = md_chars_to_number (where, 2);
00591       newval |= value & 0xfff;
00592       md_number_to_chars (where, newval, 2);
00593       break;
00594 
00595     case BFD_RELOC_BFIN_16_LOW:
00596     case BFD_RELOC_BFIN_16_HIGH:
00597       fixP->fx_done = FALSE;
00598       break;
00599 
00600     case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
00601     case BFD_RELOC_BFIN_24_PCREL_CALL_X:
00602     case BFD_RELOC_24_PCREL:
00603       if (!value)
00604        break;
00605 
00606       if (value < -16777216 || value > 16777214)
00607        as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_24");
00608 
00609       /* 25 bit offset even numbered, so we remove right bit.  */
00610       value = value >> 1;
00611       value++;
00612 
00613       md_number_to_chars (where - 2, value >> 16, 1);
00614       md_number_to_chars (where, value, 1);
00615       md_number_to_chars (where + 1, value >> 8, 1);
00616       break;
00617 
00618     case BFD_RELOC_BFIN_5_PCREL:   /* LSETUP (a, b) : "a" */
00619       if (!value)
00620        break;
00621       if (value < 4 || value > 30)
00622        as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_5");
00623       value = value >> 1;
00624       newval = md_chars_to_number (where, 1);
00625       newval = (newval & 0xf0) | (value & 0xf);
00626       md_number_to_chars (where, newval, 1);
00627       break;
00628 
00629     case BFD_RELOC_BFIN_11_PCREL:  /* LSETUP (a, b) : "b" */
00630       if (!value)
00631        break;
00632       value += 2;
00633       if (value < 4 || value > 2046)
00634        as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far BFD_RELOC_BFIN_11_PCREL");
00635       /* 11 bit unsigned even, so we remove right bit.  */
00636       value = value >> 1;
00637       newval = md_chars_to_number (where, 2);
00638       newval |= value & 0x03ff;
00639       md_number_to_chars (where, newval, 2);
00640       break;
00641 
00642     case BFD_RELOC_8:
00643       if (value < -0x80 || value >= 0x7f)
00644        as_bad_where (fixP->fx_file, fixP->fx_line, "rel too far BFD_RELOC_8");
00645       md_number_to_chars (where, value, 1);
00646       break;
00647 
00648     case BFD_RELOC_BFIN_16_IMM:
00649     case BFD_RELOC_16:
00650       if (value < -0x8000 || value >= 0x7fff)
00651        as_bad_where (fixP->fx_file, fixP->fx_line, "rel too far BFD_RELOC_8");
00652       md_number_to_chars (where, value, 2);
00653       break;
00654 
00655     case BFD_RELOC_32:
00656       md_number_to_chars (where, value, 4);
00657       break;
00658 
00659     case BFD_RELOC_BFIN_PLTPC:
00660       md_number_to_chars (where, value, 2);
00661       break;
00662 
00663     case BFD_RELOC_BFIN_FUNCDESC:
00664     case BFD_RELOC_VTABLE_INHERIT:
00665     case BFD_RELOC_VTABLE_ENTRY:
00666       fixP->fx_done = FALSE;
00667       break;
00668 
00669     default:
00670       if ((BFD_ARELOC_BFIN_PUSH > fixP->fx_r_type) || (BFD_ARELOC_BFIN_COMP < fixP->fx_r_type))
00671        {
00672          fprintf (stderr, "Relocation %d not handled in gas." " Contact support.\n", fixP->fx_r_type);
00673          return;
00674        }
00675     }
00676 
00677   if (!fixP->fx_addsy)
00678     fixP->fx_done = TRUE;
00679 
00680 }
00681 
00682 /* Round up a section size to the appropriate boundary.  */
00683 valueT
00684 md_section_align (segment, size)
00685      segT segment;
00686      valueT size;
00687 {
00688   int boundary = bfd_get_section_alignment (stdoutput, segment);
00689   return ((size + (1 << boundary) - 1) & (-1 << boundary));
00690 }
00691 
00692 
00693 /* Turn a string in input_line_pointer into a floating point
00694    constant of type type, and store the appropriate bytes in
00695    *litP.  The number of LITTLENUMS emitted is stored in *sizeP.
00696    An error message is returned, or NULL on OK.  */
00697 
00698 /* Equal to MAX_PRECISION in atof-ieee.c.  */
00699 #define MAX_LITTLENUMS 6
00700 
00701 char *
00702 md_atof (type, litP, sizeP)
00703      char   type;
00704      char * litP;
00705      int *  sizeP;
00706 {
00707   int              prec;
00708   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
00709   LITTLENUM_TYPE   *wordP;
00710   char *           t;
00711 
00712   switch (type)
00713     {
00714     case 'f':
00715     case 'F':
00716       prec = 2;
00717       break;
00718 
00719     case 'd':
00720     case 'D':
00721       prec = 4;
00722       break;
00723 
00724    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
00725 
00726     default:
00727       *sizeP = 0;
00728       return _("Bad call to md_atof()");
00729     }
00730 
00731   t = atof_ieee (input_line_pointer, type, words);
00732   if (t)
00733     input_line_pointer = t;
00734   *sizeP = prec * sizeof (LITTLENUM_TYPE);
00735 
00736   *sizeP = prec * sizeof (LITTLENUM_TYPE);
00737   /* This loops outputs the LITTLENUMs in REVERSE order; in accord with
00738      the littleendianness of the processor.  */
00739   for (wordP = words + prec - 1; prec--;)
00740     {
00741       md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
00742       litP += sizeof (LITTLENUM_TYPE);
00743     }
00744 
00745   return 0;
00746 }
00747 
00748 
00749 /* If while processing a fixup, a reloc really needs to be created
00750    then it is done here.  */
00751 
00752 arelent *
00753 tc_gen_reloc (seg, fixp)
00754      asection *seg ATTRIBUTE_UNUSED;
00755      fixS *fixp;
00756 {
00757   arelent *reloc;
00758 
00759   reloc                    = (arelent *) xmalloc (sizeof (arelent));
00760   reloc->sym_ptr_ptr  = (asymbol **) xmalloc (sizeof (asymbol *));
00761   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
00762   reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
00763 
00764   reloc->addend = fixp->fx_offset;
00765   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
00766 
00767   if (reloc->howto == (reloc_howto_type *) NULL)
00768     {
00769       as_bad_where (fixp->fx_file, fixp->fx_line,
00770                   /* xgettext:c-format.  */
00771                   _("reloc %d not supported by object file format"),
00772                   (int) fixp->fx_r_type);
00773 
00774       xfree (reloc);
00775 
00776       return NULL;
00777     }
00778 
00779   return reloc;
00780 }
00781 
00782 /*  The location from which a PC relative jump should be calculated,
00783     given a PC relative reloc.  */
00784 
00785 long
00786 md_pcrel_from_section (fixP, sec)
00787      fixS *fixP;
00788      segT sec;
00789 {
00790   if (fixP->fx_addsy != (symbolS *) NULL
00791       && (!S_IS_DEFINED (fixP->fx_addsy)
00792       || S_GET_SEGMENT (fixP->fx_addsy) != sec))
00793     {
00794       /* The symbol is undefined (or is defined but not in this section).
00795          Let the linker figure it out.  */
00796       return 0;
00797     }
00798   return fixP->fx_frag->fr_address + fixP->fx_where;
00799 }
00800 
00801 /* Return true if the fix can be handled by GAS, false if it must
00802    be passed through to the linker.  */
00803 
00804 bfd_boolean  
00805 bfin_fix_adjustable (fixS *fixP)
00806 {         
00807   switch (fixP->fx_r_type)
00808     {     
00809   /* Adjust_reloc_syms doesn't know about the GOT.  */
00810     case BFD_RELOC_BFIN_GOT:
00811     case BFD_RELOC_BFIN_GOT17M4:
00812     case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
00813     case BFD_RELOC_BFIN_PLTPC:
00814   /* We need the symbol name for the VTABLE entries.  */
00815     case BFD_RELOC_VTABLE_INHERIT:
00816     case BFD_RELOC_VTABLE_ENTRY:
00817       return 0;
00818         
00819     default:
00820       return 1;
00821     }     
00822 }
00823 
00824 
00825 /* Handle the LOOP_BEGIN and LOOP_END statements.
00826    Parse the Loop_Begin/Loop_End and create a label.  */
00827 void
00828 bfin_start_line_hook ()
00829 {
00830   bfd_boolean maybe_begin = FALSE;
00831   bfd_boolean maybe_end = FALSE;
00832 
00833   char *c1, *label_name;
00834   symbolS *line_label;
00835   char *c = input_line_pointer;
00836   int cr_num = 0;
00837 
00838   while (ISSPACE (*c))
00839     {
00840       if (*c == '\n')
00841        cr_num++;
00842       c++;
00843     }
00844 
00845   /* Look for Loop_Begin or Loop_End statements.  */
00846 
00847   if (*c != 'L' && *c != 'l')
00848     return;
00849 
00850   c++;
00851   if (*c != 'O' && *c != 'o')
00852     return;
00853 
00854   c++;
00855   if (*c != 'O' && *c != 'o')
00856     return;
00857  
00858   c++;
00859   if (*c != 'P' && *c != 'p')
00860     return;
00861 
00862   c++;
00863   if (*c != '_')
00864     return;
00865 
00866   c++;
00867   if (*c == 'E' || *c == 'e')
00868     maybe_end = TRUE;
00869   else if (*c == 'B' || *c == 'b')
00870     maybe_begin = TRUE;
00871   else
00872     return;
00873 
00874   if (maybe_end)
00875     {
00876       c++;
00877       if (*c != 'N' && *c != 'n')
00878        return;
00879 
00880       c++;
00881       if (*c != 'D' && *c != 'd')
00882         return;
00883     }
00884 
00885   if (maybe_begin)
00886     {
00887       c++;
00888       if (*c != 'E' && *c != 'e')
00889        return;
00890 
00891       c++;
00892       if (*c != 'G' && *c != 'g')
00893         return;
00894 
00895       c++;
00896       if (*c != 'I' && *c != 'i')
00897        return;
00898 
00899       c++;
00900       if (*c != 'N' && *c != 'n')
00901         return;
00902     }
00903 
00904   c++;
00905   while (ISSPACE (*c)) c++;
00906   c1 = c;
00907   while (ISALPHA (*c) || ISDIGIT (*c) || *c == '_') c++;
00908 
00909   if (input_line_pointer[-1] == '\n')
00910     bump_line_counters ();
00911 
00912   while (cr_num--)
00913     bump_line_counters ();
00914 
00915   input_line_pointer = c;
00916   if (maybe_end)
00917     {
00918       label_name = (char *) xmalloc ((c - c1) + strlen ("__END") + 1);
00919       label_name[0] = 0;
00920       strncat (label_name, c1, c-c1);
00921       strcat (label_name, "__END");
00922     }
00923   else /* maybe_begin.  */
00924     {
00925       label_name = (char *) xmalloc ((c - c1) + strlen ("__BEGIN") + 1);
00926       label_name[0] = 0;
00927       strncat (label_name, c1, c-c1);
00928       strcat (label_name, "__BEGIN");
00929     }
00930 
00931   line_label = colon (label_name);
00932 
00933   /* Loop_End follows the last instruction in the loop.
00934      Adjust label address.  */
00935   if (maybe_end)
00936     line_label->sy_value.X_add_number -= last_insn_size;
00937 
00938 }
00939 
00940 /* Special extra functions that help bfin-parse.y perform its job.  */
00941 
00942 #include <assert.h>
00943 
00944 struct obstack mempool;
00945 
00946 INSTR_T
00947 conscode (INSTR_T head, INSTR_T tail)
00948 {
00949   if (!head)
00950     return tail;
00951   head->next = tail;
00952   return head;
00953 }
00954 
00955 INSTR_T
00956 conctcode (INSTR_T head, INSTR_T tail)
00957 {
00958   INSTR_T temp = (head);
00959   if (!head)
00960     return tail;
00961   while (temp->next)
00962     temp = temp->next;
00963   temp->next = tail;
00964 
00965   return head;
00966 }
00967 
00968 INSTR_T
00969 note_reloc (INSTR_T code, Expr_Node * symbol, int reloc, int pcrel)
00970 {
00971   /* Assert that the symbol is not an operator.  */
00972   assert (symbol->type == Expr_Node_Reloc);
00973 
00974   return note_reloc1 (code, symbol->value.s_value, reloc, pcrel);
00975 
00976 }
00977 
00978 INSTR_T
00979 note_reloc1 (INSTR_T code, const char *symbol, int reloc, int pcrel)
00980 {
00981   code->reloc = reloc;
00982   code->exp = mkexpr (0, symbol_find_or_make (symbol));
00983   code->pcrel = pcrel;
00984   return code;
00985 }
00986 
00987 INSTR_T
00988 note_reloc2 (INSTR_T code, const char *symbol, int reloc, int value, int pcrel)
00989 {
00990   code->reloc = reloc;
00991   code->exp = mkexpr (value, symbol_find_or_make (symbol));
00992   code->pcrel = pcrel;
00993   return code;
00994 }
00995 
00996 INSTR_T
00997 gencode (unsigned long x)
00998 {
00999   INSTR_T cell = (INSTR_T) obstack_alloc (&mempool, sizeof (struct bfin_insn));
01000   memset (cell, 0, sizeof (struct bfin_insn));
01001   cell->value = (x);
01002   return cell;
01003 }
01004 
01005 int reloc;
01006 int ninsns;
01007 int count_insns;
01008 
01009 static void *
01010 allocate (int n)
01011 {
01012   return (void *) obstack_alloc (&mempool, n);
01013 }
01014 
01015 Expr_Node *
01016 Expr_Node_Create (Expr_Node_Type type,
01017                  Expr_Node_Value value,
01018                   Expr_Node *Left_Child,
01019                   Expr_Node *Right_Child)
01020 {
01021 
01022 
01023   Expr_Node *node = (Expr_Node *) allocate (sizeof (Expr_Node));
01024   node->type = type;
01025   node->value = value;
01026   node->Left_Child = Left_Child;
01027   node->Right_Child = Right_Child;
01028   return node;
01029 }
01030 
01031 static const char *con = ".__constant";
01032 static const char *op = ".__operator";
01033 static INSTR_T Expr_Node_Gen_Reloc_R (Expr_Node * head);
01034 INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc);
01035 
01036 INSTR_T
01037 Expr_Node_Gen_Reloc (Expr_Node * head, int parent_reloc)
01038 {
01039   /* Top level reloction expression generator VDSP style.
01040    If the relocation is just by itself, generate one item
01041    else generate this convoluted expression.  */
01042 
01043   INSTR_T note = NULL_CODE;
01044   INSTR_T note1 = NULL_CODE;
01045   int pcrel = 1;  /* Is the parent reloc pcrelative?
01046                 This calculation here and HOWTO should match.  */
01047 
01048   if (parent_reloc)
01049     {
01050       /*  If it's 32 bit quantity then 16bit code needs to be added.  */
01051       int value = 0;
01052 
01053       if (head->type == Expr_Node_Constant)
01054        {
01055          /* If note1 is not null code, we have to generate a right
01056              aligned value for the constant. Otherwise the reloc is
01057              a part of the basic command and the yacc file
01058              generates this.  */
01059          value = head->value.i_value;
01060        }
01061       switch (parent_reloc)
01062        {
01063          /*  Some relocations will need to allocate extra words.  */
01064        case BFD_RELOC_BFIN_16_IMM:
01065        case BFD_RELOC_BFIN_16_LOW:
01066        case BFD_RELOC_BFIN_16_HIGH:
01067          note1 = conscode (gencode (value), NULL_CODE);
01068          pcrel = 0;
01069          break;
01070        case BFD_RELOC_BFIN_PLTPC:
01071          note1 = conscode (gencode (value), NULL_CODE);
01072          pcrel = 0;
01073          break;
01074        case BFD_RELOC_16:
01075        case BFD_RELOC_BFIN_GOT:
01076        case BFD_RELOC_BFIN_GOT17M4:
01077        case BFD_RELOC_BFIN_FUNCDESC_GOT17M4:
01078          note1 = conscode (gencode (value), NULL_CODE);
01079          pcrel = 0;
01080          break;
01081        case BFD_RELOC_24_PCREL:
01082        case BFD_RELOC_BFIN_24_PCREL_JUMP_L:
01083        case BFD_RELOC_BFIN_24_PCREL_CALL_X:
01084          /* These offsets are even numbered pcrel.  */
01085          note1 = conscode (gencode (value >> 1), NULL_CODE);
01086          break;
01087        default:
01088          note1 = NULL_CODE;
01089        }
01090     }
01091   if (head->type == Expr_Node_Constant)
01092     note = note1;
01093   else if (head->type == Expr_Node_Reloc)
01094     {
01095       note = note_reloc1 (gencode (0), head->value.s_value, parent_reloc, pcrel);
01096       if (note1 != NULL_CODE)
01097        note = conscode (note1, note);
01098     }
01099   else if (head->type == Expr_Node_Binop
01100           && (head->value.op_value == Expr_Op_Type_Add
01101               || head->value.op_value == Expr_Op_Type_Sub)
01102           && head->Left_Child->type == Expr_Node_Reloc
01103           && head->Right_Child->type == Expr_Node_Constant)
01104     {
01105       int val = head->Right_Child->value.i_value;
01106       if (head->value.op_value == Expr_Op_Type_Sub)
01107        val = -val;
01108       note = conscode (note_reloc2 (gencode (0), head->Left_Child->value.s_value,
01109                                 parent_reloc, val, 0),
01110                      NULL_CODE);
01111       if (note1 != NULL_CODE)
01112        note = conscode (note1, note);
01113     }
01114   else
01115     {
01116       /* Call the recursive function.  */
01117       note = note_reloc1 (gencode (0), op, parent_reloc, pcrel);
01118       if (note1 != NULL_CODE)
01119        note = conscode (note1, note);
01120       note = conctcode (Expr_Node_Gen_Reloc_R (head), note);
01121     }
01122   return note;
01123 }
01124 
01125 static INSTR_T
01126 Expr_Node_Gen_Reloc_R (Expr_Node * head)
01127 {
01128 
01129   INSTR_T note = 0;
01130   INSTR_T note1 = 0;
01131 
01132   switch (head->type)
01133     {
01134     case Expr_Node_Constant:
01135       note = conscode (note_reloc2 (gencode (0), con, BFD_ARELOC_BFIN_CONST, head->value.i_value, 0), NULL_CODE);
01136       break;
01137     case Expr_Node_Reloc:
01138       note = conscode (note_reloc (gencode (0), head, BFD_ARELOC_BFIN_PUSH, 0), NULL_CODE);
01139       break;
01140     case Expr_Node_Binop:
01141       note1 = conctcode (Expr_Node_Gen_Reloc_R (head->Left_Child), Expr_Node_Gen_Reloc_R (head->Right_Child));
01142       switch (head->value.op_value)
01143        {
01144        case Expr_Op_Type_Add:
01145          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_ADD, 0), NULL_CODE));
01146          break;
01147        case Expr_Op_Type_Sub:
01148          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_SUB, 0), NULL_CODE));
01149          break;
01150        case Expr_Op_Type_Mult:
01151          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MULT, 0), NULL_CODE));
01152          break;
01153        case Expr_Op_Type_Div:
01154          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_DIV, 0), NULL_CODE));
01155          break;
01156        case Expr_Op_Type_Mod:
01157          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_MOD, 0), NULL_CODE));
01158          break;
01159        case Expr_Op_Type_Lshift:
01160          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LSHIFT, 0), NULL_CODE));
01161          break;
01162        case Expr_Op_Type_Rshift:
01163          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_RSHIFT, 0), NULL_CODE));
01164          break;
01165        case Expr_Op_Type_BAND:
01166          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_AND, 0), NULL_CODE));
01167          break;
01168        case Expr_Op_Type_BOR:
01169          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_OR, 0), NULL_CODE));
01170          break;
01171        case Expr_Op_Type_BXOR:
01172          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_XOR, 0), NULL_CODE));
01173          break;
01174        case Expr_Op_Type_LAND:
01175          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LAND, 0), NULL_CODE));
01176          break;
01177        case Expr_Op_Type_LOR:
01178          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_LOR, 0), NULL_CODE));
01179          break;
01180        default:
01181          fprintf (stderr, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__, __LINE__);
01182 
01183 
01184        }
01185       break;
01186     case Expr_Node_Unop:
01187       note1 = conscode (Expr_Node_Gen_Reloc_R (head->Left_Child), NULL_CODE);
01188       switch (head->value.op_value)
01189        {
01190        case Expr_Op_Type_NEG:
01191          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_NEG, 0), NULL_CODE));
01192          break;
01193        case Expr_Op_Type_COMP:
01194          note = conctcode (note1, conscode (note_reloc1 (gencode (0), op, BFD_ARELOC_BFIN_COMP, 0), NULL_CODE));
01195          break;
01196        default:
01197          fprintf (stderr, "%s:%d:Unkonwn operator found for arithmetic" " relocation", __FILE__, __LINE__);
01198        }
01199       break;
01200     default:
01201       fprintf (stderr, "%s:%d:Unknown node expression found during " "arithmetic relocation generation", __FILE__, __LINE__);
01202     }
01203   return note;
01204 }
01205 
01206 
01207 /* Blackfin opcode generation.  */
01208 
01209 /* These functions are called by the generated parser
01210    (from bfin-parse.y), the register type classification
01211    happens in bfin-lex.l.  */
01212 
01213 #include "bfin-aux.h"
01214 #include "opcode/bfin.h"
01215 
01216 #define INIT(t)  t c_code = init_##t
01217 #define ASSIGN(x) c_code.opcode |= ((x & c_code.mask_##x)<<c_code.bits_##x)
01218 #define ASSIGN_R(x) c_code.opcode |= (((x ? (x->regno & CODE_MASK) : 0) & c_code.mask_##x)<<c_code.bits_##x)
01219 
01220 #define HI(x) ((x >> 16) & 0xffff)
01221 #define LO(x) ((x      ) & 0xffff)
01222 
01223 #define GROUP(x) ((x->regno & CLASS_MASK) >> 4)
01224 
01225 #define GEN_OPCODE32()  \
01226        conscode (gencode (HI (c_code.opcode)), \
01227        conscode (gencode (LO (c_code.opcode)), NULL_CODE))
01228 
01229 #define GEN_OPCODE16()  \
01230        conscode (gencode (c_code.opcode), NULL_CODE)
01231 
01232 
01233 /*  32 BIT INSTRUCTIONS.  */
01234 
01235 
01236 /* DSP32 instruction generation.  */
01237 
01238 INSTR_T
01239 bfin_gen_dsp32mac (int op1, int MM, int mmod, int w1, int P,
01240                   int h01, int h11, int h00, int h10, int op0,
01241                    REG_T dst, REG_T src0, REG_T src1, int w0)
01242 {
01243   INIT (DSP32Mac);
01244 
01245   ASSIGN (op0);
01246   ASSIGN (op1);
01247   ASSIGN (MM);
01248   ASSIGN (mmod);
01249   ASSIGN (w0);
01250   ASSIGN (w1);
01251   ASSIGN (h01);
01252   ASSIGN (h11);
01253   ASSIGN (h00);
01254   ASSIGN (h10);
01255   ASSIGN (P);
01256 
01257   /* If we have full reg assignments, mask out LSB to encode
01258   single or simultaneous even/odd register moves.  */
01259   if (P)
01260     {
01261       dst->regno &= 0x06;
01262     }
01263 
01264   ASSIGN_R (dst);
01265   ASSIGN_R (src0);
01266   ASSIGN_R (src1);
01267 
01268   return GEN_OPCODE32 ();
01269 }
01270 
01271 INSTR_T
01272 bfin_gen_dsp32mult (int op1, int MM, int mmod, int w1, int P,
01273                    int h01, int h11, int h00, int h10, int op0,
01274                     REG_T dst, REG_T src0, REG_T src1, int w0)
01275 {
01276   INIT (DSP32Mult);
01277 
01278   ASSIGN (op0);
01279   ASSIGN (op1);
01280   ASSIGN (MM);
01281   ASSIGN (mmod);
01282   ASSIGN (w0);
01283   ASSIGN (w1);
01284   ASSIGN (h01);
01285   ASSIGN (h11);
01286   ASSIGN (h00);
01287   ASSIGN (h10);
01288   ASSIGN (P);
01289 
01290   if (P)
01291     {
01292       dst->regno &= 0x06;
01293     }
01294 
01295   ASSIGN_R (dst);
01296   ASSIGN_R (src0);
01297   ASSIGN_R (src1);
01298 
01299   return GEN_OPCODE32 ();
01300 }
01301 
01302 INSTR_T
01303 bfin_gen_dsp32alu (int HL, int aopcde, int aop, int s, int x,
01304               REG_T dst0, REG_T dst1, REG_T src0, REG_T src1)
01305 {
01306   INIT (DSP32Alu);
01307 
01308   ASSIGN (HL);
01309   ASSIGN (aopcde);
01310   ASSIGN (aop);
01311   ASSIGN (s);
01312   ASSIGN (x);
01313   ASSIGN_R (dst0);
01314   ASSIGN_R (dst1);
01315   ASSIGN_R (src0);
01316   ASSIGN_R (src1);
01317 
01318   return GEN_OPCODE32 ();
01319 }
01320 
01321 INSTR_T
01322 bfin_gen_dsp32shift (int sopcde, REG_T dst0, REG_T src0,
01323                 REG_T src1, int sop, int HLs)
01324 {
01325   INIT (DSP32Shift);
01326 
01327   ASSIGN (sopcde);
01328   ASSIGN (sop);
01329   ASSIGN (HLs);
01330 
01331   ASSIGN_R (dst0);
01332   ASSIGN_R (src0);
01333   ASSIGN_R (src1);
01334 
01335   return GEN_OPCODE32 ();
01336 }
01337 
01338 INSTR_T
01339 bfin_gen_dsp32shiftimm (int sopcde, REG_T dst0, int immag,
01340                    REG_T src1, int sop, int HLs)
01341 {
01342   INIT (DSP32ShiftImm);
01343 
01344   ASSIGN (sopcde);
01345   ASSIGN (sop);
01346   ASSIGN (HLs);
01347 
01348   ASSIGN_R (dst0);
01349   ASSIGN (immag);
01350   ASSIGN_R (src1);
01351 
01352   return GEN_OPCODE32 ();
01353 }
01354 
01355 /* LOOP SETUP.  */
01356 
01357 INSTR_T
01358 bfin_gen_loopsetup (Expr_Node * psoffset, REG_T c, int rop,
01359                Expr_Node * peoffset, REG_T reg)
01360 {
01361   int soffset, eoffset;
01362   INIT (LoopSetup);
01363 
01364   soffset = (EXPR_VALUE (psoffset) >> 1);
01365   ASSIGN (soffset);
01366   eoffset = (EXPR_VALUE (peoffset) >> 1);
01367   ASSIGN (eoffset);
01368   ASSIGN (rop);
01369   ASSIGN_R (c);
01370   ASSIGN_R (reg);
01371 
01372   return
01373       conscode (gencode (HI (c_code.opcode)),
01374               conctcode (Expr_Node_Gen_Reloc (psoffset, BFD_RELOC_BFIN_5_PCREL),
01375                         conctcode (gencode (LO (c_code.opcode)), Expr_Node_Gen_Reloc (peoffset, BFD_RELOC_BFIN_11_PCREL))));
01376 
01377 }
01378 
01379 /*  Call, Link.  */
01380 
01381 INSTR_T
01382 bfin_gen_calla (Expr_Node * addr, int S)
01383 {
01384   int val;
01385   int high_val;
01386   int reloc = 0;
01387   INIT (CALLa);
01388 
01389   switch(S){
01390    case 0 : reloc = BFD_RELOC_BFIN_24_PCREL_JUMP_L; break;
01391    case 1 : reloc = BFD_RELOC_24_PCREL; break;
01392    case 2 : reloc = BFD_RELOC_BFIN_PLTPC; break;
01393    default : break;
01394   }
01395 
01396   ASSIGN (S);
01397 
01398   val = EXPR_VALUE (addr) >> 1;
01399   high_val = val >> 16;
01400 
01401   return conscode (gencode (HI (c_code.opcode) | (high_val & 0xff)),
01402                      Expr_Node_Gen_Reloc (addr, reloc));
01403   }
01404 
01405 INSTR_T
01406 bfin_gen_linkage (int R, int framesize)
01407 {
01408   INIT (Linkage);
01409 
01410   ASSIGN (R);
01411   ASSIGN (framesize);
01412 
01413   return GEN_OPCODE32 ();
01414 }
01415 
01416 
01417 /* Load and Store.  */
01418 
01419 INSTR_T
01420 bfin_gen_ldimmhalf (REG_T reg, int H, int S, int Z, Expr_Node * phword, int reloc)
01421 {
01422   int grp, hword;
01423   unsigned val = EXPR_VALUE (phword);
01424   INIT (LDIMMhalf);
01425 
01426   ASSIGN (H);
01427   ASSIGN (S);
01428   ASSIGN (Z);
01429 
01430   ASSIGN_R (reg);
01431   grp = (GROUP (reg));
01432   ASSIGN (grp);
01433   if (reloc == 2)
01434     {
01435       return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, BFD_RELOC_BFIN_16_IMM));
01436     }
01437   else if (reloc == 1)
01438     {
01439       return conscode (gencode (HI (c_code.opcode)), Expr_Node_Gen_Reloc (phword, IS_H (*reg) ? BFD_RELOC_BFIN_16_HIGH : BFD_RELOC_BFIN_16_LOW));
01440     }
01441   else
01442     {
01443       hword = val;
01444       ASSIGN (hword);
01445     }
01446   return GEN_OPCODE32 ();
01447 }
01448 
01449 INSTR_T
01450 bfin_gen_ldstidxi (REG_T ptr, REG_T reg, int W, int sz, int Z, Expr_Node * poffset)
01451 {
01452   INIT (LDSTidxI);
01453 
01454   if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
01455     {
01456       fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
01457       return 0;
01458     }
01459 
01460   ASSIGN_R (ptr);
01461   ASSIGN_R (reg);
01462   ASSIGN (W);
01463   ASSIGN (sz);
01464 
01465   ASSIGN (Z);
01466 
01467   if (poffset->type != Expr_Node_Constant)
01468     {
01469       /* a GOT relocation such as R0 = [P5 + symbol@GOT] */
01470       /* distinguish between R0 = [P5 + symbol@GOT] and
01471         P5 = [P5 + _current_shared_library_p5_offset_]
01472       */
01473       if (poffset->type == Expr_Node_Reloc
01474          && !strcmp (poffset->value.s_value,
01475                     "_current_shared_library_p5_offset_"))
01476        {
01477          return  conscode (gencode (HI (c_code.opcode)),
01478                          Expr_Node_Gen_Reloc(poffset, BFD_RELOC_16));
01479        }
01480       else if (poffset->type != Expr_Node_GOT_Reloc)
01481        abort ();
01482 
01483       return conscode (gencode (HI (c_code.opcode)),
01484                      Expr_Node_Gen_Reloc(poffset->Left_Child,
01485                                       poffset->value.i_value));
01486     }
01487   else
01488     {
01489       int value, offset;
01490       switch (sz)
01491        {                           // load/store access size
01492        case 0:                     // 32 bit
01493          value = EXPR_VALUE (poffset) >> 2;
01494          break;
01495        case 1:                     // 16 bit
01496          value = EXPR_VALUE (poffset) >> 1;
01497          break;
01498        case 2:                     // 8 bit
01499          value = EXPR_VALUE (poffset);
01500          break;
01501        default:
01502          abort ();
01503        }
01504 
01505       offset = (value & 0xffff);
01506       ASSIGN (offset);
01507       return GEN_OPCODE32 ();
01508     }
01509 }
01510 
01511 
01512 INSTR_T
01513 bfin_gen_ldst (REG_T ptr, REG_T reg, int aop, int sz, int Z, int W)
01514 {
01515   INIT (LDST);
01516 
01517   if (!IS_PREG (*ptr) || (!IS_DREG (*reg) && !Z))
01518     {
01519       fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
01520       return 0;
01521     }
01522 
01523   ASSIGN_R (ptr);
01524   ASSIGN_R (reg);
01525   ASSIGN (aop);
01526   ASSIGN (sz);
01527   ASSIGN (Z);
01528   ASSIGN (W);
01529 
01530   return GEN_OPCODE16 ();
01531 }
01532 
01533 INSTR_T
01534 bfin_gen_ldstii (REG_T ptr, REG_T reg, Expr_Node * poffset, int W, int op)
01535 {
01536   int offset;
01537   int value = 0;
01538   INIT (LDSTii);
01539 
01540 
01541   if (!IS_PREG (*ptr))
01542     {
01543       fprintf (stderr, "Warning: possible mixup of Preg/Dreg\n");
01544       return 0;
01545     }
01546 
01547   switch (op)
01548     {
01549     case 1:
01550     case 2:
01551       value = EXPR_VALUE (poffset) >> 1;
01552       break;
01553     case 0:
01554     case 3:
01555       value = EXPR_VALUE (poffset) >> 2;
01556       break;
01557     }
01558 
01559   ASSIGN_R (ptr);
01560   ASSIGN_R (reg);
01561 
01562   offset = value;
01563   ASSIGN (offset);
01564   ASSIGN (W);
01565   ASSIGN (op);
01566 
01567   return GEN_OPCODE16 ();
01568 }
01569 
01570 INSTR_T
01571 bfin_gen_ldstiifp (REG_T sreg, Expr_Node * poffset, int W)
01572 {
01573   /* Set bit 4 if it's a Preg.  */
01574   int reg = (sreg->regno & CODE_MASK) | (IS_PREG (*sreg) ? 0x8 : 0x0);
01575   int offset = ((~(EXPR_VALUE (poffset) >> 2)) & 0x1f) + 1;
01576   INIT (LDSTiiFP);
01577   ASSIGN (reg);
01578   ASSIGN (offset);
01579   ASSIGN (W);
01580 
01581   return GEN_OPCODE16 ();
01582 }
01583 
01584 INSTR_T
01585 bfin_gen_ldstpmod (REG_T ptr, REG_T reg, int aop, int W, REG_T idx)
01586 {
01587   INIT (LDSTpmod);
01588 
01589   ASSIGN_R (ptr);
01590   ASSIGN_R (reg);
01591   ASSIGN (aop);
01592   ASSIGN (W);
01593   ASSIGN_R (idx);
01594 
01595   return GEN_OPCODE16 ();
01596 }
01597 
01598 INSTR_T
01599 bfin_gen_dspldst (REG_T i, REG_T reg, int aop, int W, int m)
01600 {
01601   INIT (DspLDST);
01602 
01603   ASSIGN_R (i);
01604   ASSIGN_R (reg);
01605   ASSIGN (aop);
01606   ASSIGN (W);
01607   ASSIGN (m);
01608 
01609   return GEN_OPCODE16 ();
01610 }
01611 
01612 INSTR_T
01613 bfin_gen_logi2op (int opc, int src, int dst)
01614 {
01615   INIT (LOGI2op);
01616 
01617   ASSIGN (opc);
01618   ASSIGN (src);
01619   ASSIGN (dst);
01620 
01621   return GEN_OPCODE16 ();
01622 }
01623 
01624 INSTR_T
01625 bfin_gen_brcc (int T, int B, Expr_Node * poffset)
01626 {
01627   int offset;
01628   INIT (BRCC);
01629 
01630   ASSIGN (T);
01631   ASSIGN (B);
01632   offset = ((EXPR_VALUE (poffset) >> 1));
01633   ASSIGN (offset);
01634   return conscode (gencode (c_code.opcode), Expr_Node_Gen_Reloc (poffset, BFD_RELOC_BFIN_10_PCREL));
01635 }
01636 
01637 INSTR_T
01638 bfin_gen_ujump (Expr_Node * poffset)
01639 {
01640   int offset;
01641   INIT (UJump);
01642 
01643   offset = ((EXPR_VALUE (poffset) >> 1));
01644   ASSIGN (offset);
01645 
01646   return conscode (gencode (c_code.opcode),
01647                    Expr_Node_Gen_Reloc (
01648                        poffset, BFD_RELOC_BFIN_12_PCREL_JUMP_S));
01649 }
01650 
01651 INSTR_T
01652 bfin_gen_alu2op (REG_T dst, REG_T src, int opc)
01653 {
01654   INIT (ALU2op);
01655 
01656   ASSIGN_R (dst);
01657   ASSIGN_R (src);
01658   ASSIGN (opc);
01659 
01660   return GEN_OPCODE16 ();
01661 }
01662 
01663 INSTR_T
01664 bfin_gen_compi2opd (REG_T dst, int src, int op)
01665 {
01666   INIT (COMPI2opD);
01667 
01668   ASSIGN_R (dst);
01669   ASSIGN (src);
01670   ASSIGN (op);
01671 
01672   return GEN_OPCODE16 ();
01673 }
01674 
01675 INSTR_T
01676 bfin_gen_compi2opp (REG_T dst, int src, int op)
01677 {
01678   INIT (COMPI2opP);
01679 
01680   ASSIGN_R (dst);
01681   ASSIGN (src);
01682   ASSIGN (op);
01683 
01684   return GEN_OPCODE16 ();
01685 }
01686 
01687 INSTR_T
01688 bfin_gen_dagmodik (REG_T i, int op)
01689 {
01690   INIT (DagMODik);
01691 
01692   ASSIGN_R (i);
01693   ASSIGN (op);
01694 
01695   return GEN_OPCODE16 ();
01696 }
01697 
01698 INSTR_T
01699 bfin_gen_dagmodim (REG_T i, REG_T m, int op, int br)
01700 {
01701   INIT (DagMODim);
01702 
01703   ASSIGN_R (i);
01704   ASSIGN_R (m);
01705   ASSIGN (op);
01706   ASSIGN (br);
01707 
01708   return GEN_OPCODE16 ();
01709 }
01710 
01711 INSTR_T
01712 bfin_gen_ptr2op (REG_T dst, REG_T src, int opc)
01713 {
01714   INIT (PTR2op);
01715 
01716   ASSIGN_R (dst);
01717   ASSIGN_R (src);
01718   ASSIGN (opc);
01719 
01720   return GEN_OPCODE16 ();
01721 }
01722 
01723 INSTR_T
01724 bfin_gen_comp3op (REG_T src0, REG_T src1, REG_T dst, int opc)
01725 {
01726   INIT (COMP3op);
01727 
01728   ASSIGN_R (src0);
01729   ASSIGN_R (src1);
01730   ASSIGN_R (dst);
01731   ASSIGN (opc);
01732 
01733   return GEN_OPCODE16 ();
01734 }
01735 
01736 INSTR_T
01737 bfin_gen_ccflag (REG_T x, int y, int opc, int I, int G)
01738 {
01739   INIT (CCflag);
01740 
01741   ASSIGN_R (x);
01742   ASSIGN (y);
01743   ASSIGN (opc);
01744   ASSIGN (I);
01745   ASSIGN (G);
01746 
01747   return GEN_OPCODE16 ();
01748 }
01749 
01750 INSTR_T
01751 bfin_gen_ccmv (REG_T src, REG_T dst, int T)
01752 {
01753   int s, d;
01754   INIT (CCmv);
01755 
01756   ASSIGN_R (src);
01757   ASSIGN_R (dst);
01758   s = (GROUP (src));
01759   ASSIGN (s);
01760   d = (GROUP (dst));
01761   ASSIGN (d);
01762   ASSIGN (T);
01763 
01764   return GEN_OPCODE16 ();
01765 }
01766 
01767 INSTR_T
01768 bfin_gen_cc2stat (int cbit, int op, int D)
01769 {
01770   INIT (CC2stat);
01771 
01772   ASSIGN (cbit);
01773   ASSIGN (op);
01774   ASSIGN (D);
01775 
01776   return GEN_OPCODE16 ();
01777 }
01778 
01779 INSTR_T
01780 bfin_gen_regmv (REG_T src, REG_T dst)
01781 {
01782   int gs, gd;
01783   INIT (RegMv);
01784 
01785   ASSIGN_R (src);
01786   ASSIGN_R (dst);
01787 
01788   gs = (GROUP (src));
01789   ASSIGN (gs);
01790   gd = (GROUP (dst));
01791   ASSIGN (gd);
01792 
01793   return GEN_OPCODE16 ();
01794 }
01795 
01796 INSTR_T
01797 bfin_gen_cc2dreg (int op, REG_T reg)
01798 {
01799   INIT (CC2dreg);
01800 
01801   ASSIGN (op);
01802   ASSIGN_R (reg);
01803 
01804   return GEN_OPCODE16 ();
01805 }
01806 
01807 INSTR_T
01808 bfin_gen_progctrl (int prgfunc, int poprnd)
01809 {
01810   INIT (ProgCtrl);
01811 
01812   ASSIGN (prgfunc);
01813   ASSIGN (poprnd);
01814 
01815   return GEN_OPCODE16 ();
01816 }
01817 
01818 INSTR_T
01819 bfin_gen_cactrl (REG_T reg, int a, int op)
01820 {
01821   INIT (CaCTRL);
01822 
01823   ASSIGN_R (reg);
01824   ASSIGN (a);
01825   ASSIGN (op);
01826 
01827   return GEN_OPCODE16 ();
01828 }
01829 
01830 INSTR_T
01831 bfin_gen_pushpopmultiple (int dr, int pr, int d, int p, int W)
01832 {
01833   INIT (PushPopMultiple);
01834 
01835   ASSIGN (dr);
01836   ASSIGN (pr);
01837   ASSIGN (d);
01838   ASSIGN (p);
01839   ASSIGN (W);
01840 
01841   return GEN_OPCODE16 ();
01842 }
01843 
01844 INSTR_T
01845 bfin_gen_pushpopreg (REG_T reg, int W)
01846 {
01847   int grp;
01848   INIT (PushPopReg);
01849 
01850   ASSIGN_R (reg);
01851   grp = (GROUP (reg));
01852   ASSIGN (grp);
01853   ASSIGN (W);
01854 
01855   return GEN_OPCODE16 ();
01856 }
01857 
01858 /* Pseudo Debugging Support.  */
01859 
01860 INSTR_T
01861 bfin_gen_pseudodbg (int fn, int reg, int grp)
01862 {
01863   INIT (PseudoDbg);
01864 
01865   ASSIGN (fn);
01866   ASSIGN (reg);
01867   ASSIGN (grp);
01868 
01869   return GEN_OPCODE16 ();
01870 }
01871 
01872 INSTR_T
01873 bfin_gen_pseudodbg_assert (int dbgop, REG_T regtest, int expected)
01874 {
01875   INIT (PseudoDbg_Assert);
01876 
01877   ASSIGN (dbgop);
01878   ASSIGN_R (regtest);
01879   ASSIGN (expected);
01880 
01881   return GEN_OPCODE32 ();
01882 }
01883 
01884 /* Multiple instruction generation.  */
01885 
01886 INSTR_T
01887 bfin_gen_multi_instr (INSTR_T dsp32, INSTR_T dsp16_grp1, INSTR_T dsp16_grp2)
01888 {
01889   INSTR_T walk;
01890 
01891   /* If it's a 0, convert into MNOP. */
01892   if (dsp32)
01893     {
01894       walk = dsp32->next;
01895       SET_MULTI_INSTRUCTION_BIT (dsp32);
01896     }
01897   else
01898     {
01899       dsp32 = gencode (0xc803);
01900       walk = gencode (0x1800);
01901       dsp32->next = walk;
01902     }
01903 
01904   if (!dsp16_grp1)
01905     {
01906       dsp16_grp1 = gencode (0x0000);
01907     }
01908 
01909   if (!dsp16_grp2)
01910     {
01911       dsp16_grp2 = gencode (0x0000);
01912     }
01913 
01914   walk->next = dsp16_grp1;
01915   dsp16_grp1->next = dsp16_grp2;
01916   dsp16_grp2->next = NULL_CODE;
01917 
01918   return dsp32;
01919 }
01920 
01921 INSTR_T
01922 bfin_gen_loop (Expr_Node *expr, REG_T reg, int rop, REG_T preg)
01923 {
01924   const char *loopsym;
01925   char *lbeginsym, *lendsym;
01926   Expr_Node_Value lbeginval, lendval;
01927   Expr_Node *lbegin, *lend;
01928 
01929   loopsym = expr->value.s_value;
01930   lbeginsym = (char *) xmalloc (strlen (loopsym) + strlen ("__BEGIN") + 1);
01931   lendsym = (char *) xmalloc (strlen (loopsym) + strlen ("__END") + 1);
01932 
01933   lbeginsym[0] = 0;
01934   lendsym[0] = 0;
01935 
01936   strcat (lbeginsym, loopsym);
01937   strcat (lbeginsym, "__BEGIN");
01938 
01939   strcat (lendsym, loopsym);
01940   strcat (lendsym, "__END");
01941 
01942   lbeginval.s_value = lbeginsym;
01943   lendval.s_value = lendsym;
01944 
01945   lbegin = Expr_Node_Create (Expr_Node_Reloc, lbeginval, NULL, NULL);
01946   lend   = Expr_Node_Create (Expr_Node_Reloc, lendval, NULL, NULL);
01947   return bfin_gen_loopsetup(lbegin, reg, rop, lend, preg);
01948 }
01949 
01950 bfd_boolean
01951 bfin_eol_in_insn (char *line)
01952 {
01953    /* Allow a new-line to appear in the middle of a multi-issue instruction.  */
01954 
01955    char *temp = line;
01956 
01957   if (*line != '\n')
01958     return FALSE;
01959 
01960   /* A semi-colon followed by a newline is always the end of a line.  */
01961   if (line[-1] == ';')
01962     return FALSE;
01963 
01964   if (line[-1] == '|')
01965     return TRUE;
01966 
01967   /* If the || is on the next line, there might be leading whitespace.  */
01968   temp++;
01969   while (*temp == ' ' || *temp == '\t') temp++;
01970 
01971   if (*temp == '|')
01972     return TRUE;
01973 
01974   return FALSE;
01975 }
01976 
01977 bfd_boolean
01978 bfin_start_label (char *ptr)
01979 {
01980   ptr--;
01981   while (!ISSPACE (*ptr) && !is_end_of_line[(unsigned char) *ptr])
01982     ptr--;
01983 
01984   ptr++;
01985   if (*ptr == '(' || *ptr == '[')
01986     return FALSE;
01987 
01988   return TRUE;
01989 } 
01990 
01991 int
01992 bfin_force_relocation (struct fix *fixp)
01993 {
01994   if (fixp->fx_r_type ==BFD_RELOC_BFIN_16_LOW
01995       || fixp->fx_r_type == BFD_RELOC_BFIN_16_HIGH)
01996     return TRUE;
01997 
01998   return generic_force_reloc (fixp);
01999 }