Back to index

cell-binutils  2.17cvs20070401
cgen.c
Go to the documentation of this file.
00001 /* GAS interface for targets using CGEN: Cpu tools GENerator.
00002    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
00003    2006 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 Software
00019    Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include <setjmp.h>
00022 #include "as.h"
00023 #include "symcat.h"
00024 #include "cgen-desc.h"
00025 #include "subsegs.h"
00026 #include "cgen.h"
00027 #include "dwarf2dbg.h"
00028 
00029 #include "symbols.h"
00030 #include "struc-symbol.h"
00031 
00032 #ifdef OBJ_COMPLEX_RELC
00033 static expressionS * make_right_shifted_expr
00034   (expressionS *, const int, const int);
00035 
00036 static unsigned long gas_cgen_encode_addend
00037   (const unsigned long, const unsigned long, const unsigned long, \
00038    const unsigned long, const unsigned long, const unsigned long, \
00039    const unsigned long);
00040 
00041 static char * weak_operand_overflow_check
00042   (const expressionS *, const CGEN_OPERAND *);
00043 
00044 static void queue_fixup_recursively
00045   (const int, const int, expressionS *, \
00046    const CGEN_MAYBE_MULTI_IFLD *, const int, const int);
00047 
00048 static int rightshift = 0;
00049 #endif
00050 static void queue_fixup (int, int, expressionS *);
00051 
00052 /* Opcode table descriptor, must be set by md_begin.  */
00053 
00054 CGEN_CPU_DESC gas_cgen_cpu_desc;
00055 
00056 /* Callback to insert a register into the symbol table.
00057    A target may choose to let GAS parse the registers.
00058    ??? Not currently used.  */
00059 
00060 void
00061 cgen_asm_record_register (name, number)
00062      char *name;
00063      int number;
00064 {
00065   /* Use symbol_create here instead of symbol_new so we don't try to
00066      output registers into the object file's symbol table.  */
00067   symbol_table_insert (symbol_create (name, reg_section,
00068                                   number, &zero_address_frag));
00069 }
00070 
00071 /* We need to keep a list of fixups.  We can't simply generate them as
00072    we go, because that would require us to first create the frag, and
00073    that would screw up references to ``.''.
00074 
00075    This is used by cpu's with simple operands.  It keeps knowledge of what
00076    an `expressionS' is and what a `fixup' is out of CGEN which for the time
00077    being is preferable.
00078 
00079    OPINDEX is the index in the operand table.
00080    OPINFO is something the caller chooses to help in reloc determination.  */
00081 
00082 struct fixup
00083 {
00084   int opindex;
00085   int opinfo;
00086   expressionS exp;
00087   struct cgen_maybe_multi_ifield * field;
00088   int msb_field_p;
00089 };
00090 
00091 static struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
00092 static int num_fixups;
00093 
00094 /* Prepare to parse an instruction.
00095    ??? May wish to make this static and delete calls in md_assemble.  */
00096 
00097 void
00098 gas_cgen_init_parse ()
00099 {
00100   num_fixups = 0;
00101 }
00102 
00103 /* Queue a fixup.  */
00104 
00105 static void
00106 queue_fixup (opindex, opinfo, expP)
00107      int           opindex;
00108      int           opinfo;
00109      expressionS * expP;
00110 {
00111   /* We need to generate a fixup for this expression.  */
00112   if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
00113     as_fatal (_("too many fixups"));
00114   fixups[num_fixups].exp     = *expP;
00115   fixups[num_fixups].opindex = opindex;
00116   fixups[num_fixups].opinfo  = opinfo;
00117   ++ num_fixups;
00118 }
00119 
00120 /* The following functions allow fixup chains to be stored, retrieved,
00121    and swapped.  They are a generalization of a pre-existing scheme
00122    for storing, restoring and swapping fixup chains that was used by
00123    the m32r port.  The functionality is essentially the same, only
00124    instead of only being able to store a single fixup chain, an entire
00125    array of fixup chains can be stored.  It is the user's responsibility
00126    to keep track of how many fixup chains have been stored and which
00127    elements of the array they are in.
00128 
00129    The algorithms used are the same as in the old scheme.  Other than the
00130    "array-ness" of the whole thing, the functionality is identical to the
00131    old scheme.
00132 
00133    gas_cgen_initialize_saved_fixups_array():
00134       Sets num_fixups_in_chain to 0 for each element. Call this from
00135       md_begin() if you plan to use these functions and you want the
00136       fixup count in each element to be set to 0 initially.  This is
00137       not necessary, but it's included just in case.  It performs
00138       the same function for each element in the array of fixup chains
00139       that gas_init_parse() performs for the current fixups.
00140 
00141    gas_cgen_save_fixups (element):
00142       element - element number of the array you wish to store the fixups
00143                 to.  No mechanism is built in for tracking what element
00144                 was last stored to.
00145 
00146    gas_cgen_restore_fixups (element):
00147       element - element number of the array you wish to restore the fixups
00148                 from.
00149 
00150    gas_cgen_swap_fixups(int element):
00151        element - swap the current fixups with those in this element number.
00152 */
00153 
00154 struct saved_fixups
00155 {
00156   struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
00157   int num_fixups_in_chain;
00158 };
00159 
00160 static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
00161 
00162 void
00163 gas_cgen_initialize_saved_fixups_array ()
00164 {
00165   int i = 0;
00166 
00167   while (i < MAX_SAVED_FIXUP_CHAINS)
00168     stored_fixups[i++].num_fixups_in_chain = 0;
00169 }
00170 
00171 void
00172 gas_cgen_save_fixups (i)
00173      int i;
00174 {
00175   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
00176     {
00177       as_fatal ("index into stored_fixups[] out of bounds");
00178       return;
00179     }
00180 
00181   stored_fixups[i].num_fixups_in_chain = num_fixups;
00182   memcpy (stored_fixups[i].fixup_chain, fixups,
00183          sizeof (fixups[0]) * num_fixups);
00184   num_fixups = 0;
00185 }
00186 
00187 void
00188 gas_cgen_restore_fixups (i)
00189      int i;
00190 {
00191   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
00192     {
00193       as_fatal ("index into stored_fixups[] out of bounds");
00194       return;
00195     }
00196 
00197   num_fixups = stored_fixups[i].num_fixups_in_chain;
00198   memcpy (fixups, stored_fixups[i].fixup_chain,
00199          (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
00200   stored_fixups[i].num_fixups_in_chain = 0;
00201 }
00202 
00203 void
00204 gas_cgen_swap_fixups (i)
00205      int i;
00206 {
00207   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
00208     {
00209       as_fatal ("index into stored_fixups[] out of bounds");
00210       return;
00211     }
00212 
00213   if (num_fixups == 0)
00214     gas_cgen_restore_fixups (i);
00215 
00216   else if (stored_fixups[i].num_fixups_in_chain == 0)
00217     gas_cgen_save_fixups (i);
00218 
00219   else
00220     {
00221       int tmp;
00222       struct fixup tmp_fixup;
00223 
00224       tmp = stored_fixups[i].num_fixups_in_chain;
00225       stored_fixups[i].num_fixups_in_chain = num_fixups;
00226       num_fixups = tmp;
00227 
00228       for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
00229        {
00230          tmp_fixup = stored_fixups[i].fixup_chain [tmp];
00231          stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
00232          fixups [tmp] = tmp_fixup;
00233        }
00234     }
00235 }
00236 
00237 /* Default routine to record a fixup.
00238    This is a cover function to fix_new.
00239    It exists because we record INSN with the fixup.
00240 
00241    FRAG and WHERE are their respective arguments to fix_new_exp.
00242    LENGTH is in bits.
00243    OPINFO is something the caller chooses to help in reloc determination.
00244 
00245    At this point we do not use a bfd_reloc_code_real_type for
00246    operands residing in the insn, but instead just use the
00247    operand index.  This lets us easily handle fixups for any
00248    operand type.  We pick a BFD reloc type in md_apply_fix.  */
00249 
00250 fixS *
00251 gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
00252      fragS *              frag;
00253      int                  where;
00254      const CGEN_INSN *    insn;
00255      int                  length;
00256      const CGEN_OPERAND * operand;
00257      int                  opinfo;
00258      symbolS *            symbol;
00259      offsetT              offset;
00260 {
00261   fixS *fixP;
00262 
00263   /* It may seem strange to use operand->attrs and not insn->attrs here,
00264      but it is the operand that has a pc relative relocation.  */
00265   fixP = fix_new (frag, where, length / 8, symbol, offset,
00266                 CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
00267                 (bfd_reloc_code_real_type)
00268                   ((int) BFD_RELOC_UNUSED
00269                    + (int) operand->type));
00270   fixP->fx_cgen.insn = insn;
00271   fixP->fx_cgen.opinfo = opinfo;
00272   fixP->fx_cgen.field = NULL;
00273   fixP->fx_cgen.msb_field_p = 0;
00274 
00275   return fixP;
00276 }
00277 
00278 /* Default routine to record a fixup given an expression.
00279    This is a cover function to fix_new_exp.
00280    It exists because we record INSN with the fixup.
00281 
00282    FRAG and WHERE are their respective arguments to fix_new_exp.
00283    LENGTH is in bits.
00284    OPINFO is something the caller chooses to help in reloc determination.
00285 
00286    At this point we do not use a bfd_reloc_code_real_type for
00287    operands residing in the insn, but instead just use the
00288    operand index.  This lets us easily handle fixups for any
00289    operand type.  We pick a BFD reloc type in md_apply_fix.  */
00290 
00291 fixS *
00292 gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
00293      fragS *              frag;
00294      int                  where;
00295      const CGEN_INSN *    insn;
00296      int                  length;
00297      const CGEN_OPERAND * operand;
00298      int                  opinfo;
00299      expressionS *        exp;
00300 {
00301   fixS *fixP;
00302 
00303   /* It may seem strange to use operand->attrs and not insn->attrs here,
00304      but it is the operand that has a pc relative relocation.  */
00305   fixP = fix_new_exp (frag, where, length / 8, exp,
00306                     CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
00307                     (bfd_reloc_code_real_type)
00308                       ((int) BFD_RELOC_UNUSED
00309                       + (int) operand->type));
00310   fixP->fx_cgen.insn = insn;
00311   fixP->fx_cgen.opinfo = opinfo;
00312   fixP->fx_cgen.field = NULL;
00313   fixP->fx_cgen.msb_field_p = 0;
00314 
00315   return fixP;
00316 }
00317 
00318 #ifdef OBJ_COMPLEX_RELC
00319 static symbolS *
00320 expr_build_binary (operatorT op, symbolS * s1, symbolS * s2)
00321 {
00322   expressionS e;
00323 
00324   e.X_op = op;
00325   e.X_add_symbol = s1;
00326   e.X_op_symbol = s2;
00327   e.X_add_number = 0;
00328   return make_expr_symbol (& e);
00329 }
00330 #endif
00331 
00332 /* Used for communication between the next two procedures.  */
00333 static jmp_buf expr_jmp_buf;
00334 static int expr_jmp_buf_p;
00335 
00336 /* Callback for cgen interface.  Parse the expression at *STRP.
00337    The result is an error message or NULL for success (in which case
00338    *STRP is advanced past the parsed text).
00339    WANT is an indication of what the caller is looking for.
00340    If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
00341    a table entry with the insn, reset the queued fixups counter.
00342    An enum cgen_parse_operand_result is stored in RESULTP.
00343    OPINDEX is the operand's table entry index.
00344    OPINFO is something the caller chooses to help in reloc determination.
00345    The resulting value is stored in VALUEP.  */
00346 
00347 const char *
00348 gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
00349 
00350 #ifdef OBJ_COMPLEX_RELC
00351      CGEN_CPU_DESC cd;
00352 #else
00353      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
00354 #endif
00355      enum cgen_parse_operand_type want;
00356      const char **strP;
00357      int opindex;
00358      int opinfo;
00359      enum cgen_parse_operand_result *resultP;
00360      bfd_vma *valueP;
00361 {
00362 #ifdef __STDC__
00363   /* These are volatile to survive the setjmp.  */
00364   char * volatile hold;
00365   enum cgen_parse_operand_result * volatile resultP_1;
00366   volatile int opinfo_1;
00367 #else
00368   static char *hold;
00369   static enum cgen_parse_operand_result *resultP_1;
00370   int opinfo_1;
00371 #endif
00372   const char *errmsg;
00373   expressionS exp;
00374 
00375 #ifdef OBJ_COMPLEX_RELC
00376   volatile int              signed_p = 0;
00377   symbolS *                 stmp = NULL;
00378   bfd_reloc_code_real_type  reloc_type;
00379   const CGEN_OPERAND *      operand;
00380   fixS                      dummy_fixup;
00381 #endif
00382   if (want == CGEN_PARSE_OPERAND_INIT)
00383     {
00384       gas_cgen_init_parse ();
00385       return NULL;
00386     }
00387 
00388   resultP_1 = resultP;
00389   hold = input_line_pointer;
00390   input_line_pointer = (char *) *strP;
00391   opinfo_1 = opinfo;
00392 
00393   /* We rely on md_operand to longjmp back to us.
00394      This is done via gas_cgen_md_operand.  */
00395   if (setjmp (expr_jmp_buf) != 0)
00396     {
00397       expr_jmp_buf_p = 0;
00398       input_line_pointer = (char *) hold;
00399       *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
00400       return _("illegal operand");
00401     }
00402 
00403   expr_jmp_buf_p = 1;
00404   expression (&exp);
00405   expr_jmp_buf_p = 0;
00406   errmsg = NULL;
00407 
00408   *strP = input_line_pointer;
00409   input_line_pointer = hold;
00410 
00411 #ifdef TC_CGEN_PARSE_FIX_EXP
00412   opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
00413 #endif 
00414 
00415   /* FIXME: Need to check `want'.  */
00416 
00417   switch (exp.X_op)
00418     {
00419     case O_illegal:
00420       errmsg = _("illegal operand");
00421       *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
00422       break;
00423     case O_absent:
00424       errmsg = _("missing operand");
00425       *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
00426       break;
00427     case O_constant:
00428       if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
00429        goto de_fault;
00430       *valueP = exp.X_add_number;
00431       *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
00432       break;
00433     case O_register:
00434       *valueP = exp.X_add_number;
00435       *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
00436       break;
00437     de_fault:
00438     default:
00439 #ifdef OBJ_COMPLEX_RELC
00440       /* Look up operand, check to see if there's an obvious
00441         overflow (this helps disambiguate some insn parses).  */
00442       operand = cgen_operand_lookup_by_num (cd, opindex);
00443       errmsg = weak_operand_overflow_check (& exp, operand);
00444 
00445       if (! errmsg)
00446        {
00447          /* Fragment the expression as necessary, and queue a reloc.  */
00448          memset (& dummy_fixup, 0, sizeof (fixS));
00449 
00450          reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);
00451 
00452          if (exp.X_op == O_symbol
00453              && reloc_type == BFD_RELOC_RELC
00454              && exp.X_add_symbol->sy_value.X_op == O_constant
00455              && exp.X_add_symbol->bsym->section != expr_section
00456              && exp.X_add_symbol->bsym->section != absolute_section
00457              && exp.X_add_symbol->bsym->section != undefined_section)
00458            {
00459              /* Local labels will have been (eagerly) turned into constants
00460                by now, due to the inappropriately deep insight of the
00461                expression parser.  Unfortunately make_expr_symbol
00462                prematurely dives into the symbol evaluator, and in this
00463                case it gets a bad answer, so we manually create the
00464                expression symbol we want here.  */
00465              stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
00466                                 & zero_address_frag);
00467              symbol_set_value_expression (stmp, & exp);
00468            } 
00469          else 
00470            stmp = make_expr_symbol (& exp);
00471 
00472          /* If this is a pc-relative RELC operand, we
00473             need to subtract "." from the expression.  */        
00474          if (reloc_type == BFD_RELOC_RELC
00475              && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
00476            stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ()); 
00477 
00478          /* FIXME: this is not a perfect heuristic for figuring out
00479             whether an operand is signed: it only works when the operand
00480             is an immediate. it's not terribly likely that any other
00481             values will be signed relocs, but it's possible. */
00482          if (operand && (operand->hw_type == HW_H_SINT))
00483            signed_p = 1;
00484          
00485          if (stmp->bsym && (stmp->bsym->section == expr_section))
00486            {
00487              if (signed_p)
00488               stmp->bsym->flags |= BSF_SRELC;
00489              else
00490               stmp->bsym->flags |= BSF_RELC;
00491            }
00492          
00493          /* Now package it all up for the fixup emitter.  */
00494          exp.X_op = O_symbol;
00495          exp.X_op_symbol = 0;
00496          exp.X_add_symbol = stmp;
00497          exp.X_add_number = 0;
00498              
00499          /* Re-init rightshift quantity, just in case.  */
00500          rightshift = operand->length;
00501          queue_fixup_recursively (opindex, opinfo_1, & exp,  
00502                                (reloc_type == BFD_RELOC_RELC) ?
00503                                & (operand->index_fields) : 0,
00504                                signed_p, -1);
00505        }
00506       * resultP = errmsg
00507        ? CGEN_PARSE_OPERAND_RESULT_ERROR
00508        : CGEN_PARSE_OPERAND_RESULT_QUEUED;
00509       *valueP = 0;
00510 #else
00511       queue_fixup (opindex, opinfo_1, &exp);
00512       *valueP = 0;
00513       *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
00514 #endif      
00515       break;
00516     }
00517 
00518   return errmsg;
00519 }
00520 
00521 /* md_operand handler to catch unrecognized expressions and halt the
00522    parsing process so the next entry can be tried.
00523 
00524    ??? This could be done differently by adding code to `expression'.  */
00525 
00526 void
00527 gas_cgen_md_operand (expressionP)
00528      expressionS *expressionP ATTRIBUTE_UNUSED;
00529 {
00530   /* Don't longjmp if we're not called from within cgen_parse_operand().  */
00531   if (expr_jmp_buf_p)
00532     longjmp (expr_jmp_buf, 1);
00533 }
00534 
00535 /* Finish assembling instruction INSN.
00536    BUF contains what we've built up so far.
00537    LENGTH is the size of the insn in bits.
00538    RELAX_P is non-zero if relaxable insns should be emitted as such.
00539    Otherwise they're emitted in non-relaxable forms.
00540    The "result" is stored in RESULT if non-NULL.  */
00541 
00542 void
00543 gas_cgen_finish_insn (insn, buf, length, relax_p, result)
00544      const CGEN_INSN *insn;
00545      CGEN_INSN_BYTES_PTR buf;
00546      unsigned int length;
00547      int relax_p;
00548      finished_insnS *result;
00549 {
00550   int i;
00551   int relax_operand;
00552   char *f;
00553   unsigned int byte_len = length / 8;
00554 
00555   /* ??? Target foo issues various warnings here, so one might want to provide
00556      a hook here.  However, our caller is defined in tc-foo.c so there
00557      shouldn't be a need for a hook.  */
00558 
00559   /* Write out the instruction.
00560      It is important to fetch enough space in one call to `frag_more'.
00561      We use (f - frag_now->fr_literal) to compute where we are and we
00562      don't want frag_now to change between calls.
00563 
00564      Relaxable instructions: We need to ensure we allocate enough
00565      space for the largest insn.  */
00566 
00567   if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
00568     /* These currently shouldn't get here.  */
00569     abort ();
00570 
00571   /* Is there a relaxable insn with the relaxable operand needing a fixup?  */
00572 
00573   relax_operand = -1;
00574   if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
00575     {
00576       /* Scan the fixups for the operand affected by relaxing
00577         (i.e. the branch address).  */
00578 
00579       for (i = 0; i < num_fixups; ++i)
00580        {
00581          if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
00582                                    CGEN_OPERAND_RELAX))
00583            {
00584              relax_operand = i;
00585              break;
00586            }
00587        }
00588     }
00589 
00590   if (relax_operand != -1)
00591     {
00592       int max_len;
00593       fragS *old_frag;
00594       expressionS *exp;
00595       symbolS *sym;
00596       offsetT off;
00597 
00598 #ifdef TC_CGEN_MAX_RELAX
00599       max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
00600 #else
00601       max_len = CGEN_MAX_INSN_SIZE;
00602 #endif
00603       /* Ensure variable part and fixed part are in same fragment.  */
00604       /* FIXME: Having to do this seems like a hack.  */
00605       frag_grow (max_len);
00606 
00607       /* Allocate space for the fixed part.  */
00608       f = frag_more (byte_len);
00609 
00610       /* Create a relaxable fragment for this instruction.  */
00611       old_frag = frag_now;
00612 
00613       exp = &fixups[relax_operand].exp;
00614       sym = exp->X_add_symbol;
00615       off = exp->X_add_number;
00616       if (exp->X_op != O_constant && exp->X_op != O_symbol)
00617        {
00618          /* Handle complex expressions.  */
00619          sym = make_expr_symbol (exp);
00620          off = 0;
00621        }
00622 
00623       frag_var (rs_machine_dependent,
00624               max_len - byte_len /* max chars */,
00625               0 /* variable part already allocated */,
00626               /* FIXME: When we machine generate the relax table,
00627                  machine generate a macro to compute subtype.  */
00628               1 /* subtype */,
00629               sym,
00630               off,
00631               f);
00632 
00633       /* Record the operand number with the fragment so md_convert_frag
00634         can use gas_cgen_md_record_fixup to record the appropriate reloc.  */
00635       old_frag->fr_cgen.insn    = insn;
00636       old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
00637       old_frag->fr_cgen.opinfo  = fixups[relax_operand].opinfo;
00638       if (result)
00639        result->frag = old_frag;
00640     }
00641   else
00642     {
00643       f = frag_more (byte_len);
00644       if (result)
00645        result->frag = frag_now;
00646     }
00647 
00648   /* If we're recording insns as numbers (rather than a string of bytes),
00649      target byte order handling is deferred until now.  */
00650 #if CGEN_INT_INSN_P
00651   cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) f, length, *buf);
00652 #else
00653   memcpy (f, buf, byte_len);
00654 #endif
00655 
00656   /* Emit DWARF2 debugging information.  */
00657   dwarf2_emit_insn (byte_len);
00658 
00659   /* Create any fixups.  */
00660   for (i = 0; i < num_fixups; ++i)
00661     {
00662       fixS *fixP;
00663       const CGEN_OPERAND *operand =
00664        cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex);
00665 
00666       /* Don't create fixups for these.  That's done during relaxation.
00667         We don't need to test for CGEN_INSN_RELAXED as they can't get here
00668         (see above).  */
00669       if (relax_p
00670          && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE)
00671          && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_RELAX))
00672        continue;
00673 
00674 #ifndef md_cgen_record_fixup_exp
00675 #define md_cgen_record_fixup_exp gas_cgen_record_fixup_exp
00676 #endif
00677 
00678       fixP = md_cgen_record_fixup_exp (frag_now, f - frag_now->fr_literal,
00679                                    insn, length, operand,
00680                                    fixups[i].opinfo,
00681                                    &fixups[i].exp);
00682       fixP->fx_cgen.field = fixups[i].field;
00683       fixP->fx_cgen.msb_field_p = fixups[i].msb_field_p;
00684       if (result)
00685        result->fixups[i] = fixP;
00686     }
00687 
00688   if (result)
00689     {
00690       result->num_fixups = num_fixups;
00691       result->addr = f;
00692     }
00693 }
00694 
00695 #ifdef OBJ_COMPLEX_RELC
00696 /* Queue many fixups, recursively. If the field is a multi-ifield,
00697    repeatedly queue its sub-parts, right shifted to fit into the field (we
00698    assume here multi-fields represent a left-to-right, MSB0-LSB0
00699    reading). */
00700 
00701 static void
00702 queue_fixup_recursively (const int                      opindex,
00703                       const int                      opinfo,
00704                       expressionS *                  expP,
00705                       const CGEN_MAYBE_MULTI_IFLD *  field,
00706                       const int                      signed_p,
00707                       const int                      part_of_multi)
00708 {
00709   if (field && field->count)
00710     {
00711       int i;
00712   
00713       for (i = 0; i < field->count; ++ i)
00714        queue_fixup_recursively (opindex, opinfo, expP, 
00715                              & (field->val.multi[i]), signed_p, i);
00716     }
00717   else
00718     {
00719       expressionS * new_exp = expP;
00720 
00721 #ifdef DEBUG
00722       printf ("queueing fixup for field %s\n",
00723              (field ? field->val.leaf->name : "??"));
00724       print_symbol_value (expP->X_add_symbol);
00725 #endif
00726       if (field && part_of_multi != -1)
00727        {
00728          rightshift -= field->val.leaf->length;
00729 
00730          /* Shift reloc value by number of bits remaining after this
00731             field.  */
00732          if (rightshift)
00733            new_exp = make_right_shifted_expr (expP, rightshift, signed_p);     
00734        }
00735       
00736       /* Truncate reloc values to length, *after* leftmost one.  */
00737       fixups[num_fixups].msb_field_p = (part_of_multi <= 0);
00738       fixups[num_fixups].field = (CGEN_MAYBE_MULTI_IFLD *) field;
00739       
00740       queue_fixup (opindex, opinfo, new_exp);
00741     }
00742 }
00743 
00744 /* Encode the self-describing RELC reloc format's addend.  */
00745 
00746 static unsigned long 
00747 gas_cgen_encode_addend (const unsigned long start,    /* in bits */
00748                      const unsigned long len,      /* in bits */
00749                      const unsigned long oplen,    /* in bits */
00750                      const unsigned long wordsz,   /* in bytes */
00751                      const unsigned long chunksz,  /* in bytes */
00752                      const unsigned long signed_p,
00753                      const unsigned long trunc_p)
00754 {
00755   unsigned long res = 0L;
00756 
00757   res |= start    & 0x3F;
00758   res |= (oplen   & 0x3F) << 6;
00759   res |= (len     & 0x3F) << 12;
00760   res |= (wordsz  & 0xF)  << 18;
00761   res |= (chunksz & 0xF)  << 22;
00762   res |= (CGEN_INSN_LSB0_P ? 1 : 0) << 27;
00763   res |= signed_p << 28;
00764   res |= trunc_p << 29;
00765 
00766   return res;
00767 }
00768 
00769 /* Purpose: make a weak check that the expression doesn't overflow the
00770    operand it's to be inserted into.
00771 
00772    Rationale: some insns used to use %operators to disambiguate during a
00773    parse. when these %operators are translated to expressions by the macro
00774    expander, the ambiguity returns. we attempt to disambiguate by field
00775    size.
00776    
00777    Method: check to see if the expression's top node is an O_and operator,
00778    and the mask is larger than the operand length. This would be an
00779    overflow, so signal it by returning an error string. Any other case is
00780    ambiguous, so we assume it's OK and return NULL.  */
00781 
00782 static char *
00783 weak_operand_overflow_check (const expressionS *  exp,
00784                           const CGEN_OPERAND * operand)
00785 {
00786   const unsigned long len = operand->length;
00787   unsigned long mask;
00788   unsigned long opmask = (((1L << (len - 1)) - 1) << 1) | 1;
00789 
00790   if (!exp)
00791     return NULL;
00792 
00793   if (exp->X_op != O_bit_and)
00794     {
00795       /* Check for implicit overflow flag.  */
00796       if (CGEN_OPERAND_ATTR_VALUE 
00797          (operand, CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW))
00798        return _("a reloc on this operand implies an overflow");
00799       return NULL;
00800     }
00801   
00802   mask = exp->X_add_number;
00803 
00804   if (exp->X_add_symbol &&
00805       exp->X_add_symbol->sy_value.X_op == O_constant)
00806     mask |= exp->X_add_symbol->sy_value.X_add_number;
00807 
00808   if (exp->X_op_symbol &&
00809       exp->X_op_symbol->sy_value.X_op == O_constant)
00810     mask |= exp->X_op_symbol->sy_value.X_add_number;
00811 
00812   /* Want to know if mask covers more bits than opmask. 
00813      this is the same as asking if mask has any bits not in opmask,
00814      or whether (mask & ~opmask) is nonzero.  */
00815   if (mask && (mask & ~opmask))
00816     {
00817 #ifdef DEBUG
00818       printf ("overflow: (mask = %8.8x, ~opmask = %8.8x, AND = %8.8x)\n",
00819              mask, ~opmask, (mask & ~opmask));
00820 #endif
00821       return _("operand mask overflow");
00822     }
00823 
00824   return NULL;  
00825 }
00826 
00827 
00828 static expressionS *
00829 make_right_shifted_expr (expressionS * exp,
00830                       const int     amount,
00831                       const int     signed_p)
00832 {
00833   symbolS * stmp = 0;
00834   expressionS * new_exp;
00835 
00836   stmp = expr_build_binary (O_right_shift, 
00837                          make_expr_symbol (exp),
00838                          expr_build_uconstant (amount));
00839   
00840   if (signed_p)
00841     stmp->bsym->flags |= BSF_SRELC;
00842   else
00843     stmp->bsym->flags |= BSF_RELC;
00844   
00845   /* Then wrap that in a "symbol expr" for good measure.  */
00846   new_exp = xmalloc (sizeof (expressionS));
00847   memset (new_exp, 0, sizeof (expressionS));
00848   new_exp->X_op = O_symbol;
00849   new_exp->X_op_symbol = 0;
00850   new_exp->X_add_symbol = stmp;
00851   new_exp->X_add_number = 0;
00852   
00853   return new_exp;
00854 }
00855 #endif
00856 /* Apply a fixup to the object code.  This is called for all the
00857    fixups we generated by the call to fix_new_exp, above.  In the call
00858    above we used a reloc code which was the largest legal reloc code
00859    plus the operand index.  Here we undo that to recover the operand
00860    index.  At this point all symbol values should be fully resolved,
00861    and we attempt to completely resolve the reloc.  If we can not do
00862    that, we determine the correct reloc code and put it back in the fixup.  */
00863 
00864 /* FIXME: This function handles some of the fixups and bfd_install_relocation
00865    handles the rest.  bfd_install_relocation (or some other bfd function)
00866    should handle them all.  */
00867 
00868 void
00869 gas_cgen_md_apply_fix (fixP, valP, seg)
00870      fixS *   fixP;
00871      valueT * valP;
00872      segT     seg ATTRIBUTE_UNUSED;
00873 {
00874   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
00875   valueT value = * valP;
00876   /* Canonical name, since used a lot.  */
00877   CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
00878 
00879   if (fixP->fx_addsy == (symbolS *) NULL)
00880     fixP->fx_done = 1;
00881 
00882   /* We don't actually support subtracting a symbol.  */
00883   if (fixP->fx_subsy != (symbolS *) NULL)
00884     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
00885 
00886   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
00887     {
00888       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
00889       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (cd, opindex);
00890       const char *errmsg;
00891       bfd_reloc_code_real_type reloc_type;
00892       CGEN_FIELDS *fields = alloca (CGEN_CPU_SIZEOF_FIELDS (cd));
00893       const CGEN_INSN *insn = fixP->fx_cgen.insn;
00894       int start;
00895       int length;
00896       int signed_p = 0;
00897 
00898       if (fixP->fx_cgen.field)
00899        {            
00900          /* Use the twisty little pointer path
00901             back to the ifield if it exists.  */
00902          start = fixP->fx_cgen.field->val.leaf->start;
00903          length = fixP->fx_cgen.field->val.leaf->length;
00904        }
00905       else
00906        {
00907          /* Or the far less useful operand-size guesstimate.  */
00908          start = operand->start;
00909          length = operand->length;
00910        }
00911 
00912       /* FIXME: this is not a perfect heuristic for figuring out
00913          whether an operand is signed: it only works when the operand
00914          is an immediate. it's not terribly likely that any other
00915          values will be signed relocs, but it's possible. */
00916       if (operand && (operand->hw_type == HW_H_SINT))
00917         signed_p = 1;
00918 
00919       /* If the reloc has been fully resolved finish the operand here.  */
00920       /* FIXME: This duplicates the capabilities of code in BFD.  */
00921       if (fixP->fx_done
00922          /* FIXME: If partial_inplace isn't set bfd_install_relocation won't
00923             finish the job.  Testing for pcrel is a temporary hack.  */
00924          || fixP->fx_pcrel)
00925        {
00926          CGEN_CPU_SET_FIELDS_BITSIZE (cd) (fields, CGEN_INSN_BITSIZE (insn));
00927          CGEN_CPU_SET_VMA_OPERAND (cd) (cd, opindex, fields, (bfd_vma) value);
00928 
00929 #if CGEN_INT_INSN_P
00930          {
00931            CGEN_INSN_INT insn_value =
00932              cgen_get_insn_value (cd, (unsigned char *) where,
00933                                CGEN_INSN_BITSIZE (insn));
00934 
00935            /* ??? 0 is passed for `pc'.  */
00936            errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
00937                                              &insn_value, (bfd_vma) 0);
00938            cgen_put_insn_value (cd, (unsigned char *) where,
00939                              CGEN_INSN_BITSIZE (insn), insn_value);
00940          }
00941 #else
00942          /* ??? 0 is passed for `pc'.  */
00943          errmsg = CGEN_CPU_INSERT_OPERAND (cd) (cd, opindex, fields,
00944                                            (unsigned char *) where,
00945                                            (bfd_vma) 0);
00946 #endif
00947          if (errmsg)
00948            as_bad_where (fixP->fx_file, fixP->fx_line, "%s", errmsg);
00949        }
00950 
00951       if (fixP->fx_done)
00952        return;
00953 
00954       /* The operand isn't fully resolved.  Determine a BFD reloc value
00955         based on the operand information and leave it to
00956         bfd_install_relocation.  Note that this doesn't work when
00957         partial_inplace == false.  */
00958 
00959       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
00960 #ifdef OBJ_COMPLEX_RELC
00961       if (reloc_type == BFD_RELOC_RELC)
00962        {
00963          /* Change addend to "self-describing" form,
00964             for BFD to handle in the linker.  */
00965          value = gas_cgen_encode_addend (start, operand->length,
00966                                      length, fixP->fx_size, 
00967                                      cd->insn_chunk_bitsize / 8, 
00968                                      signed_p, 
00969                                      ! (fixP->fx_cgen.msb_field_p));
00970        }
00971 #endif
00972 
00973       if (reloc_type != BFD_RELOC_NONE)
00974        fixP->fx_r_type = reloc_type;
00975       else
00976        {
00977          as_bad_where (fixP->fx_file, fixP->fx_line,
00978                      _("unresolved expression that must be resolved"));
00979          fixP->fx_done = 1;
00980          return;
00981        }
00982     }
00983   else if (fixP->fx_done)
00984     {
00985       /* We're finished with this fixup.  Install it because
00986         bfd_install_relocation won't be called to do it.  */
00987       switch (fixP->fx_r_type)
00988        {
00989        case BFD_RELOC_8:
00990          md_number_to_chars (where, value, 1);
00991          break;
00992        case BFD_RELOC_16:
00993          md_number_to_chars (where, value, 2);
00994          break;
00995        case BFD_RELOC_32:
00996          md_number_to_chars (where, value, 4);
00997          break;
00998        case BFD_RELOC_64:
00999          md_number_to_chars (where, value, 8);
01000          break;
01001        default:
01002          as_bad_where (fixP->fx_file, fixP->fx_line,
01003                      _("internal error: can't install fix for reloc type %d (`%s')"),
01004                      fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
01005          break;
01006        }
01007     }
01008   /* else
01009      bfd_install_relocation will be called to finish things up.  */
01010 
01011   /* Tuck `value' away for use by tc_gen_reloc.
01012      See the comment describing fx_addnumber in write.h.
01013      This field is misnamed (or misused :-).  */
01014   fixP->fx_addnumber = value;
01015 }
01016 
01017 /* Translate internal representation of relocation info to BFD target format.
01018 
01019    FIXME: To what extent can we get all relevant targets to use this?  */
01020 
01021 arelent *
01022 gas_cgen_tc_gen_reloc (section, fixP)
01023      asection * section ATTRIBUTE_UNUSED;
01024      fixS *     fixP;
01025 {
01026   arelent *reloc;
01027   reloc = (arelent *) xmalloc (sizeof (arelent));
01028 
01029   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
01030   if (reloc->howto == (reloc_howto_type *) NULL)
01031     {
01032       as_bad_where (fixP->fx_file, fixP->fx_line,
01033                   _("relocation is not supported"));
01034       return NULL;
01035     }
01036 
01037   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
01038 
01039   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
01040   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
01041 
01042   /* Use fx_offset for these cases.  */
01043   if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
01044       || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
01045     reloc->addend = fixP->fx_offset;
01046   else
01047     reloc->addend = fixP->fx_addnumber;
01048 
01049   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
01050   return reloc;
01051 }
01052 
01053 /* Perform any cgen specific initialisation.
01054    Called after gas_cgen_cpu_desc has been created.  */
01055 
01056 void
01057 gas_cgen_begin ()
01058 {
01059   if (flag_signed_overflow_ok)
01060     cgen_set_signed_overflow_ok (gas_cgen_cpu_desc);
01061   else
01062     cgen_clear_signed_overflow_ok (gas_cgen_cpu_desc);
01063 }
01064