(linenum→info "unix/slp.c:2238")

binutils/2.18/gas/cgen.c

    1: /* GAS interface for targets using CGEN: Cpu tools GENerator.
    2:    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3:    2006, 2007 Free Software Foundation, Inc.
    4: 
    5:    This file is part of GAS, the GNU Assembler.
    6: 
    7:    GAS is free software; you can redistribute it and/or modify
    8:    it under the terms of the GNU General Public License as published by
    9:    the Free Software Foundation; either version 3, or (at your option)
   10:    any later version.
   11: 
   12:    GAS is distributed in the hope that it will be useful, but WITHOUT
   13:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   14:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   15:    License for more details.
   16: 
   17:    You should have received a copy of the GNU General Public License
   18:    along with GAS; see the file COPYING.  If not, write to the Free Software
   19:    Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
   20: 
   21: #include <setjmp.h>
   22: #include "as.h"
   23: #include "symcat.h"
   24: #include "cgen-desc.h"
   25: #include "subsegs.h"
   26: #include "cgen.h"
   27: #include "dwarf2dbg.h"
   28: 
   29: #include "symbols.h"
   30: #include "struc-symbol.h"
   31: 
   32: #ifdef OBJ_COMPLEX_RELC
   33: static expressionS * make_right_shifted_expr
   34:   (expressionS *, const int, const int);
   35: 
   36: static unsigned long gas_cgen_encode_addend
   37:   (const unsigned long, const unsigned long, const unsigned long, \
   38:    const unsigned long, const unsigned long, const unsigned long, \
   39:    const unsigned long);
   40: 
   41: static char * weak_operand_overflow_check
   42:   (const expressionS *, const CGEN_OPERAND *);
   43: 
   44: static void queue_fixup_recursively
   45:   (const int, const int, expressionS *, \
   46:    const CGEN_MAYBE_MULTI_IFLD *, const int, const int);
   47: 
   48: static int rightshift = 0;
   49: #endif
   50: static void queue_fixup (int, int, expressionS *);
   51: 
   52: /* Opcode table descriptor, must be set by md_begin.  */
   53: 
   54: CGEN_CPU_DESC gas_cgen_cpu_desc;
   55: 
   56: /* Callback to insert a register into the symbol table.
   57:    A target may choose to let GAS parse the registers.
   58:    ??? Not currently used.  */
   59: 
   60: void
   61: cgen_asm_record_register (name, number)
   62:      char *name;
   63:      int number;
   64: {
   65:   /* Use symbol_create here instead of symbol_new so we don't try to
   66:      output registers into the object file's symbol table.  */
   67:   symbol_table_insert (symbol_create (name, reg_section,
   68:                                       number, &zero_address_frag));
   69: }
   70: 
   71: /* We need to keep a list of fixups.  We can't simply generate them as
   72:    we go, because that would require us to first create the frag, and
   73:    that would screw up references to ``.''.
   74: 
   75:    This is used by cpu's with simple operands.  It keeps knowledge of what
   76:    an `expressionS' is and what a `fixup' is out of CGEN which for the time
   77:    being is preferable.
   78: 
   79:    OPINDEX is the index in the operand table.
   80:    OPINFO is something the caller chooses to help in reloc determination.  */
   81: 
   82: struct fixup
   83: {
   84:   int opindex;
   85:   int opinfo;
   86:   expressionS exp;
   87:   struct cgen_maybe_multi_ifield * field;
   88:   int msb_field_p;
   89: };
   90: 
   91: static struct fixup fixups[GAS_CGEN_MAX_FIXUPS];
   92: static int num_fixups;
   93: 
   94: /* Prepare to parse an instruction.
   95:    ??? May wish to make this static and delete calls in md_assemble.  */
   96: 
   97: void
   98: gas_cgen_init_parse ()
   99: {
  100:   num_fixups = 0;
  101: }
  102: 
  103: /* Queue a fixup.  */
  104: 
  105: static void
  106: queue_fixup (opindex, opinfo, expP)
  107:      int           opindex;
  108:      int           opinfo;
  109:      expressionS * expP;
  110: {
  111:   /* We need to generate a fixup for this expression.  */
  112:   if (num_fixups >= GAS_CGEN_MAX_FIXUPS)
  113:     as_fatal (_("too many fixups"));
  114:   fixups[num_fixups].exp     = *expP;
  115:   fixups[num_fixups].opindex = opindex;
  116:   fixups[num_fixups].opinfo  = opinfo;
  117:   ++ num_fixups;
  118: }
  119: 
  120: /* The following functions allow fixup chains to be stored, retrieved,
  121:    and swapped.  They are a generalization of a pre-existing scheme
  122:    for storing, restoring and swapping fixup chains that was used by
  123:    the m32r port.  The functionality is essentially the same, only
  124:    instead of only being able to store a single fixup chain, an entire
  125:    array of fixup chains can be stored.  It is the user's responsibility
  126:    to keep track of how many fixup chains have been stored and which
  127:    elements of the array they are in.
  128: 
  129:    The algorithms used are the same as in the old scheme.  Other than the
  130:    "array-ness" of the whole thing, the functionality is identical to the
  131:    old scheme.
  132: 
  133:    gas_cgen_initialize_saved_fixups_array():
  134:       Sets num_fixups_in_chain to 0 for each element. Call this from
  135:       md_begin() if you plan to use these functions and you want the
  136:       fixup count in each element to be set to 0 initially.  This is
  137:       not necessary, but it's included just in case.  It performs
  138:       the same function for each element in the array of fixup chains
  139:       that gas_init_parse() performs for the current fixups.
  140: 
  141:    gas_cgen_save_fixups (element):
  142:       element - element number of the array you wish to store the fixups
  143:                 to.  No mechanism is built in for tracking what element
  144:                 was last stored to.
  145: 
  146:    gas_cgen_restore_fixups (element):
  147:       element - element number of the array you wish to restore the fixups
  148:                 from.
  149: 
  150:    gas_cgen_swap_fixups(int element):
  151:        element - swap the current fixups with those in this element number.
  152: */
  153: 
  154: struct saved_fixups
  155: {
  156:   struct fixup fixup_chain[GAS_CGEN_MAX_FIXUPS];
  157:   int num_fixups_in_chain;
  158: };
  159: 
  160: static struct saved_fixups stored_fixups[MAX_SAVED_FIXUP_CHAINS];
  161: 
  162: void
  163: gas_cgen_initialize_saved_fixups_array ()
  164: {
  165:   int i = 0;
  166: 
  167:   while (i < MAX_SAVED_FIXUP_CHAINS)
  168:     stored_fixups[i++].num_fixups_in_chain = 0;
  169: }
  170: 
  171: void
  172: gas_cgen_save_fixups (i)
  173:      int i;
  174: {
  175:   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
  176:     {
  177:       as_fatal ("index into stored_fixups[] out of bounds");
  178:       return;
  179:     }
  180: 
  181:   stored_fixups[i].num_fixups_in_chain = num_fixups;
  182:   memcpy (stored_fixups[i].fixup_chain, fixups,
  183:           sizeof (fixups[0]) * num_fixups);
  184:   num_fixups = 0;
  185: }
  186: 
  187: void
  188: gas_cgen_restore_fixups (i)
  189:      int i;
  190: {
  191:   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
  192:     {
  193:       as_fatal ("index into stored_fixups[] out of bounds");
  194:       return;
  195:     }
  196: 
  197:   num_fixups = stored_fixups[i].num_fixups_in_chain;
  198:   memcpy (fixups, stored_fixups[i].fixup_chain,
  199:           (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups);
  200:   stored_fixups[i].num_fixups_in_chain = 0;
  201: }
  202: 
  203: void
  204: gas_cgen_swap_fixups (i)
  205:      int i;
  206: {
  207:   if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS)
  208:     {
  209:       as_fatal ("index into stored_fixups[] out of bounds");
  210:       return;
  211:     }
  212: 
  213:   if (num_fixups == 0)
  214:     gas_cgen_restore_fixups (i);
  215: 
  216:   else if (stored_fixups[i].num_fixups_in_chain == 0)
  217:     gas_cgen_save_fixups (i);
  218: 
  219:   else
  220:     {
  221:       int tmp;
  222:       struct fixup tmp_fixup;
  223: 
  224:       tmp = stored_fixups[i].num_fixups_in_chain;
  225:       stored_fixups[i].num_fixups_in_chain = num_fixups;
  226:       num_fixups = tmp;
  227: 
  228:       for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;)
  229:         {
  230:           tmp_fixup = stored_fixups[i].fixup_chain [tmp];
  231:           stored_fixups[i].fixup_chain[tmp] = fixups [tmp];
  232:           fixups [tmp] = tmp_fixup;
  233:         }
  234:     }
  235: }
  236: 
  237: /* Default routine to record a fixup.
  238:    This is a cover function to fix_new.
  239:    It exists because we record INSN with the fixup.
  240: 
  241:    FRAG and WHERE are their respective arguments to fix_new_exp.
  242:    LENGTH is in bits.
  243:    OPINFO is something the caller chooses to help in reloc determination.
  244: 
  245:    At this point we do not use a bfd_reloc_code_real_type for
  246:    operands residing in the insn, but instead just use the
  247:    operand index.  This lets us easily handle fixups for any
  248:    operand type.  We pick a BFD reloc type in md_apply_fix.  */
  249: 
  250: fixS *
  251: gas_cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
  252:      fragS *              frag;
  253:      int                  where;
  254:      const CGEN_INSN *    insn;
  255:      int                  length;
  256:      const CGEN_OPERAND * operand;
  257:      int                  opinfo;
  258:      symbolS *            symbol;
  259:      offsetT              offset;
  260: {
  261:   fixS *fixP;
  262: 
  263:   /* It may seem strange to use operand->attrs and not insn->attrs here,
  264:      but it is the operand that has a pc relative relocation.  */
  265:   fixP = fix_new (frag, where, length / 8, symbol, offset,
  266:                   CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
  267:                   (bfd_reloc_code_real_type)
  268:                     ((int) BFD_RELOC_UNUSED
  269:                      + (int) operand->type));
  270:   fixP->fx_cgen.insn = insn;
  271:   fixP->fx_cgen.opinfo = opinfo;
  272:   fixP->fx_cgen.field = NULL;
  273:   fixP->fx_cgen.msb_field_p = 0;
  274: 
  275:   return fixP;
  276: }
  277: 
  278: /* Default routine to record a fixup given an expression.
  279:    This is a cover function to fix_new_exp.
  280:    It exists because we record INSN with the fixup.
  281: 
  282:    FRAG and WHERE are their respective arguments to fix_new_exp.
  283:    LENGTH is in bits.
  284:    OPINFO is something the caller chooses to help in reloc determination.
  285: 
  286:    At this point we do not use a bfd_reloc_code_real_type for
  287:    operands residing in the insn, but instead just use the
  288:    operand index.  This lets us easily handle fixups for any
  289:    operand type.  We pick a BFD reloc type in md_apply_fix.  */
  290: 
  291: fixS *
  292: gas_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
  293:      fragS *              frag;
  294:      int                  where;
  295:      const CGEN_INSN *    insn;
  296:      int                  length;
  297:      const CGEN_OPERAND * operand;
  298:      int                  opinfo;
  299:      expressionS *        exp;
  300: {
  301:   fixS *fixP;
  302: 
  303:   /* It may seem strange to use operand->attrs and not insn->attrs here,
  304:      but it is the operand that has a pc relative relocation.  */
  305:   fixP = fix_new_exp (frag, where, length / 8, exp,
  306:                       CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR),
  307:                       (bfd_reloc_code_real_type)
  308:                         ((int) BFD_RELOC_UNUSED
  309:                          + (int) operand->type));
  310:   fixP->fx_cgen.insn = insn;
  311:   fixP->fx_cgen.opinfo = opinfo;
  312:   fixP->fx_cgen.field = NULL;
  313:   fixP->fx_cgen.msb_field_p = 0;
  314: 
  315:   return fixP;
  316: }
  317: 
  318: #ifdef OBJ_COMPLEX_RELC
  319: static symbolS *
  320: expr_build_binary (operatorT op, symbolS * s1, symbolS * s2)
  321: {
  322:   expressionS e;
  323: 
  324:   e.X_op = op;
  325:   e.X_add_symbol = s1;
  326:   e.X_op_symbol = s2;
  327:   e.X_add_number = 0;
  328:   return make_expr_symbol (& e);
  329: }
  330: #endif
  331: 
  332: /* Used for communication between the next two procedures.  */
  333: static jmp_buf expr_jmp_buf;
  334: static int expr_jmp_buf_p;
  335: 
  336: /* Callback for cgen interface.  Parse the expression at *STRP.
  337:    The result is an error message or NULL for success (in which case
  338:    *STRP is advanced past the parsed text).
  339:    WANT is an indication of what the caller is looking for.
  340:    If WANT == CGEN_ASM_PARSE_INIT the caller is beginning to try to match
  341:    a table entry with the insn, reset the queued fixups counter.
  342:    An enum cgen_parse_operand_result is stored in RESULTP.
  343:    OPINDEX is the operand's table entry index.
  344:    OPINFO is something the caller chooses to help in reloc determination.
  345:    The resulting value is stored in VALUEP.  */
  346: 
  347: const char *
  348: gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
  349: 
  350: #ifdef OBJ_COMPLEX_RELC
  351:      CGEN_CPU_DESC cd;
  352: #else
  353:      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
  354: #endif
  355:      enum cgen_parse_operand_type want;
  356:      const char **strP;
  357:      int opindex;
  358:      int opinfo;
  359:      enum cgen_parse_operand_result *resultP;
  360:      bfd_vma *valueP;
  361: {
  362: #ifdef __STDC__
  363:   /* These are volatile to survive the setjmp.  */
  364:   char * volatile hold;
  365:   enum cgen_parse_operand_result * volatile resultP_1;
  366:   volatile int opinfo_1;
  367: #else
  368:   static char *hold;
  369:   static enum cgen_parse_operand_result *resultP_1;
  370:   int opinfo_1;
  371: #endif
  372:   const char *errmsg;
  373:   expressionS exp;
  374: 
  375: #ifdef OBJ_COMPLEX_RELC
  376:   volatile int              signed_p = 0;
  377:   symbolS *                 stmp = NULL;
  378:   bfd_reloc_code_real_type  reloc_type;
  379:   const CGEN_OPERAND *      operand;
  380:   fixS                      dummy_fixup;
  381: #endif
  382:   if (want == CGEN_PARSE_OPERAND_INIT)
  383:     {
  384:       gas_cgen_init_parse ();
  385:       return NULL;
  386:     }
  387: 
  388:   resultP_1 = resultP;
  389:   hold = input_line_pointer;
  390:   input_line_pointer = (char *) *strP;
  391:   opinfo_1 = opinfo;
  392: 
  393:   /* We rely on md_operand to longjmp back to us.
  394:      This is done via gas_cgen_md_operand.  */
  395:   if (setjmp (expr_jmp_buf) != 0)
  396:     {
  397:       expr_jmp_buf_p = 0;
  398:       input_line_pointer = (char *) hold;
  399:       *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
  400:       return _("illegal operand");
  401:     }
  402: 
  403:   expr_jmp_buf_p = 1;
  404:   expression (&exp);
  405:   expr_jmp_buf_p = 0;
  406:   errmsg = NULL;
  407: 
  408:   *strP = input_line_pointer;
  409:   input_line_pointer = hold;
  410: 
  411: #ifdef TC_CGEN_PARSE_FIX_EXP
  412:   opinfo_1 = TC_CGEN_PARSE_FIX_EXP (opinfo_1, & exp);
  413: #endif 
  414: 
  415:   /* FIXME: Need to check `want'.  */
  416: 
  417:   switch (exp.X_op)
  418:     {
  419:     case O_illegal:
  420:       errmsg = _("illegal operand");
  421:       *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
  422:       break;
  423:     case O_absent:
  424:       errmsg = _("missing operand");
  425:       *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
  426:       break;
  427:     case O_constant:
  428:       if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
  429:         goto de_fault;
  430:       *valueP = exp.X_add_number;
  431:       *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
  432:       break;
  433:     case O_register:
  434:       *valueP = exp.X_add_number;
  435:       *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
  436:       break;
  437:     de_fault:
  438:     default:
  439: #ifdef OBJ_COMPLEX_RELC
  440:       /* Look up operand, check to see if there's an obvious
  441:          overflow (this helps disambiguate some insn parses).  */
  442:       operand = cgen_operand_lookup_by_num (cd, opindex);
  443:       errmsg = weak_operand_overflow_check (& exp, operand);
  444: 
  445:       if (! errmsg)
  446:         {
  447:           /* Fragment the expression as necessary, and queue a reloc.  */
  448:           memset (& dummy_fixup, 0, sizeof (fixS));
  449: 
  450:           reloc_type = md_cgen_lookup_reloc (0, operand, & dummy_fixup);
  451: 
  452:           if (exp.X_op == O_symbol
  453:               && reloc_type == BFD_RELOC_RELC
  454:               && exp.X_add_symbol->sy_value.X_op == O_constant
  455:               && exp.X_add_symbol->bsym->section != expr_section
  456:               && exp.X_add_symbol->bsym->section != absolute_section
  457:               && exp.X_add_symbol->bsym->section != undefined_section)
  458:             {
  459:               /* Local labels will have been (eagerly) turned into constants
  460:                  by now, due to the inappropriately deep insight of the
  461:                  expression parser.  Unfortunately make_expr_symbol
  462:                  prematurely dives into the symbol evaluator, and in this
  463:                  case it gets a bad answer, so we manually create the
  464:                  expression symbol we want here.  */
  465:               stmp = symbol_create (FAKE_LABEL_NAME, expr_section, 0,
  466:                                     & zero_address_frag);
  467:               symbol_set_value_expression (stmp, & exp);
  468:             } 
  469:           else 
  470:             stmp = make_expr_symbol (& exp);
  471: 
  472:           /* If this is a pc-relative RELC operand, we
  473:              need to subtract "." from the expression.  */       
  474:           if (reloc_type == BFD_RELOC_RELC
  475:               && CGEN_OPERAND_ATTR_VALUE (operand, CGEN_OPERAND_PCREL_ADDR))
  476:             stmp = expr_build_binary (O_subtract, stmp, expr_build_dot ()); 
  477: 
  478:           /* FIXME: this is not a perfect heuristic for figuring out
  479:              whether an operand is signed: it only works when the operand
  480:              is an immediate. it's not terribly likely that any other
  481:              values will be signed relocs, but it's possible. */
  482:           if (operand && (operand->hw_type == HW_H_SINT))
  483:             signed_p = 1;
  484:           
  485:           if (stmp->bsym && (stmp->bsym->section == expr_section))
  486:             {
  487:               if (signed_p)
  488:                 stmp->bsym->flags |= BSF_SRELC;
  489:               else
  490:                 stmp->bsym->flags |= BSF_RELC;
  491:             }
  492:           
  493:           /* Now package it all up for the fixup emitter.  */
  494:           exp.X_op = O_symbol;
  495:           exp.X_op_symbol = 0;
  496:           exp.X_add_symbol = stmp;
  497:           exp.X_add_number = 0;
  498:               
  499:           /* Re-init rightshift quantity, just in case.  */
  500:           rightshift = operand->length;
  501:           queue_fixup_recursively (opindex, opinfo_1, & exp,  
  502:                                    (reloc_type == BFD_RELOC_RELC) ?
  503:                                    & (operand->index_fields) : 0,
  504:                                    signed_p, -1);
  505:         }
  506:       * resultP = errmsg
  507:         ? CGEN_PARSE_OPERAND_RESULT_ERROR
  508:         : CGEN_PARSE_OPERAND_RESULT_QUEUED;
  509:       *valueP = 0;
  510: #else
  511:       queue_fixup (opindex, opinfo_1, &exp);
  512:       *valueP = 0;
  513:       *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
  514: #endif      
  515:       break;
  516:     }
  517: 
  518:   return errmsg;
  519: }
  520: 
  521: /* md_operand handler to catch unrecognized expressions and halt the
  522:    parsing process so the next entry can be tried.
  523: 
  524:    ??? This could be done differently by adding code to `expression'.  */
  525: 
  526: void
  527: gas_cgen_md_operand (expressionP)
  528:      expressionS *expressionP ATTRIBUTE_UNUSED;
  529: {
  530:   /* Don't longjmp if we're not called from within cgen_parse_operand().  */
  531:   if (expr_jmp_buf_p)
  532:     longjmp (expr_jmp_buf, 1);
  533: }
  534: 
  535: /* Finish assembling instruction INSN.
  536:    BUF contains what we've built up so far.
  537:    LENGTH is the size of the insn in bits.
  538:    RELAX_P is non-zero if relaxable insns should be emitted as such.
  539:    Otherwise they're emitted in non-relaxable forms.
  540:    The "result" is stored in RESULT if non-NULL.  */
  541: 
  542: void
  543: gas_cgen_finish_insn (insn, buf, length, relax_p, result)
  544:      const CGEN_INSN *insn;
  545:      CGEN_INSN_BYTES_PTR buf;
  546:      unsigned int length;
  547:      int relax_p;
  548:      finished_insnS *result;
  549: {
  550:   int i;
  551:   int relax_operand;
  552:   char *f;
  553:   unsigned int byte_len = length / 8;
  554: 
  555:   /* ??? Target foo issues various warnings here, so one might want to provide
  556:      a hook here.  However, our caller is defined in tc-foo.c so there
  557:      shouldn't be a need for a hook.  */
  558: 
  559:   /* Write out the instruction.
  560:      It is important to fetch enough space in one call to `frag_more'.
  561:      We use (f - frag_now->fr_literal) to compute where we are and we
  562:      don't want frag_now to change between calls.
  563: 
  564:      Relaxable instructions: We need to ensure we allocate enough
  565:      space for the largest insn.  */
  566: 
  567:   if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED))
  568:     /* These currently shouldn't get here.  */
  569:     abort ();
  570: 
  571:   /* Is there a relaxable insn with the relaxable operand needing a fixup?  */
  572: 
  573:   relax_operand = -1;
  574:   if (relax_p && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXABLE))
  575:     {
  576:       /* Scan the fixups for the operand affected by relaxing
  577:          (i.e. the branch address).  */
  578: 
  579:       for (i = 0; i < num_fixups; ++i)
  580:         {
  581:           if (CGEN_OPERAND_ATTR_VALUE (cgen_operand_lookup_by_num (gas_cgen_cpu_desc, fixups[i].opindex),
  582:                                        CGEN_OPERAND_RELAX))
  583:             {
  584:               relax_operand = i;
  585:               break;
  586:             }
  587:         }
  588:     }
  589: 
  590:   if (relax_operand != -1)
  591:     {
  592:       int max_len;
  593:       fragS *old_frag;
  594:       expressionS *exp;
  595:       symbolS *sym;
  596:       offsetT off;
  597: 
  598: #ifdef TC_CGEN_MAX_RELAX
  599:       max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
  600: #else
  601:       max_len = CGEN_MAX_INSN_SIZE;
  602: #endif
  603:       /* Ensure variable part and fixed part are in same fragment.  */
  604:       /* FIXME: Having to do this seems like a hack.  */
  605:       frag_grow (max_len);
  606: 
  607:       /* Allocate space for the fixed part.  */
  608:       f = frag_more (byte_len);
  609: 
  610:       /* Create a relaxable fragment for this instruction.  */
  611:       old_frag = frag_now;
  612: 
  613:       exp = &fixups[relax_operand].exp