void frag_append_1_char (int datum) { frag_alloc_check (&frchain_now->frch_obstack); if (obstack_room (&frchain_now->frch_obstack) <= 1) { frag_wane (frag_now); frag_new (0); } obstack_1grow (&frchain_now->frch_obstack, datum); }
void frag_grow (unsigned int nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { long oldc; long newc; /* Try to allocate a bit more than needed right now. But don't do this if we would waste too much memory. Especially necessary for extremely big (like 2GB initialized) frags. */ if (nchars < 0x10000) newc = 2 * nchars; else newc = nchars + 0x10000; newc += SIZEOF_STRUCT_FRAG; /* Check for possible overflow. */ if (newc < 0) as_fatal (_("can't extend frag %u chars"), nchars); /* Force to allocate at least NEWC bytes, but not less than the default. */ oldc = obstack_chunk_size (&frchain_now->frch_obstack); if (newc > oldc) obstack_chunk_size (&frchain_now->frch_obstack) = newc; while (obstack_room (&frchain_now->frch_obstack) < nchars) { /* Not enough room in this frag. Close it and start a new one. This must be done in a loop because the created frag may not be big enough if the current obstack chunk is used. */ frag_wane (frag_now); frag_new (0); } /* Restore the old chunk size. */ obstack_chunk_size (&frchain_now->frch_obstack) = oldc; } }
static void frag_var_init (relax_stateT type, int max_chars, int var, relax_substateT subtype, symbolS *symbol, offsetT offset, char *opcode) { frag_now->fr_var = var; frag_now->fr_type = type; frag_now->fr_subtype = subtype; frag_now->fr_symbol = symbol; frag_now->fr_offset = offset; frag_now->fr_opcode = opcode; #ifdef USING_CGEN frag_now->fr_cgen.insn = 0; frag_now->fr_cgen.opindex = 0; frag_now->fr_cgen.opinfo = 0; #endif #ifdef TC_FRAG_INIT TC_FRAG_INIT (frag_now); #endif as_where (&frag_now->fr_file, &frag_now->fr_line); frag_new (max_chars); }
/* * frag_var() * * Start a new frag unless we have max_chars more chars of room in the current frag. * Close off the old frag with a .fill 0. * * Set up a machine_dependent relaxable frag, then start a new frag. * Return the address of the 1st char of the var part of the old frag * to write into. */ char * frag_var( relax_stateT type, int max_chars, int var, relax_substateT subtype, symbolS *symbol, long offset, char *opcode) { register char *retval; frag_grow (max_chars); retval = obstack_next_free (&frags); obstack_blank_fast (&frags, max_chars); frag_now->fr_var = var; frag_now->fr_type = type; frag_now->fr_subtype = subtype; frag_now->fr_symbol = symbol; frag_now->fr_offset = offset; frag_now->fr_opcode = opcode; frag_new (max_chars); return (retval); } /* frag_var() */
void md_assemble (char *str) { frv_insn insn; char *errmsg; int packing_constraint; finished_insnS finished_insn; fragS *double_nop_frag = NULL; fragS *single_nop_frag = NULL; struct vliw_insn_list *vliw_insn_list_entry = NULL; /* Initialize GAS's cgen interface for a new instruction. */ gas_cgen_init_parse (); memset (&insn, 0, sizeof (insn)); insn.insn = frv_cgen_assemble_insn (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg); if (!insn.insn) { as_bad ("%s", errmsg); return; } /* If the cpu is tomcat, then we need to insert nops to workaround hardware limitations. We need to keep track of each vliw unit and examine the length of the unit and the individual insns within the unit to determine the number and location of the required nops. */ if (frv_mach == bfd_mach_frvtomcat) { /* If we've just finished a VLIW insn OR this is a branch, then start up a new frag. Fill it with nops. We will get rid of those that are not required after we've seen all of the instructions but before we start resolving fixups. */ if ( !FRV_IS_NOP (insn) && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) { char *buffer; frag_wane (frag_now); frag_new (0); double_nop_frag = frag_now; buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0); md_number_to_chars (buffer, FRV_NOP_PACK, 4); md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4); frag_wane (frag_now); frag_new (0); single_nop_frag = frag_now; buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0); md_number_to_chars (buffer, FRV_NOP_NOPACK, 4); } vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT); vliw_insn_list_entry->insn = insn.insn; if (frv_is_branch_insn (insn.insn)) vliw_insn_list_entry->type = VLIW_BRANCH_TYPE; if ( !FRV_IS_NOP (insn) && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack)) { vliw_insn_list_entry->snop_frag = single_nop_frag; vliw_insn_list_entry->dnop_frag = double_nop_frag; } } /* Make sure that this insn does not violate the VLIW packing constraints. */ /* -mno-pack disallows any packing whatsoever. */ if (frv_flags & EF_FRV_NOPACK) { if (! insn.fields.f_pack) { as_bad (_("VLIW packing used for -mno-pack")); return; } } /* -mcpu=FRV is an idealized FR-V implementation that supports all of the instructions, don't do vliw checking. */ else if (frv_mach != bfd_mach_frv) { if (!target_implements_insn_p (insn.insn)) { as_bad (_("Instruction not supported by this architecture")); return; } packing_constraint = frv_vliw_add_insn (& vliw, insn.insn); if (frv_mach == bfd_mach_fr550 && ! packing_constraint) packing_constraint = fr550_check_acc_range (& vliw, & insn); if (insn.fields.f_pack) frv_vliw_reset (& vliw, frv_mach, frv_flags); if (packing_constraint) { as_bad (_("VLIW packing constraint violation")); return; } } /* Doesn't really matter what we pass for RELAX_P here. */ gas_cgen_finish_insn (insn.insn, insn.buffer, CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn); /* If the cpu is tomcat, then we need to insert nops to workaround hardware limitations. We need to keep track of each vliw unit and examine the length of the unit and the individual insns within the unit to determine the number and location of the required nops. */ if (frv_mach == bfd_mach_frvtomcat) { if (vliw_insn_list_entry) vliw_insn_list_entry->address = finished_insn.addr; else abort(); if (insn.fields.f_pack) { /* We've completed a VLIW insn. */ previous_vliw_chain = current_vliw_chain; current_vliw_chain = NULL; current_vliw_insn = NULL; } } }
static void new_frag (void) { frag_wane (frag_now); frag_new (0); }