forked from Imagelibrary/binutils-gdb
Add support for parallel instructions.
This commit is contained in:
189
gas/cgen.c
189
gas/cgen.c
@@ -30,13 +30,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
void
|
||||
cgen_asm_record_register (name, number)
|
||||
char *name;
|
||||
int number;
|
||||
char * name;
|
||||
int number;
|
||||
{
|
||||
/* Use symbol_create here instead of symbol_new so we don't try to
|
||||
output registers into the object file's symbol table. */
|
||||
symbol_table_insert (symbol_create (name, reg_section,
|
||||
number, &zero_address_frag));
|
||||
number, & zero_address_frag));
|
||||
}
|
||||
|
||||
/* We need to keep a list of fixups. We can't simply generate them as
|
||||
@@ -52,15 +52,15 @@ cgen_asm_record_register (name, number)
|
||||
|
||||
struct fixup
|
||||
{
|
||||
int opindex;
|
||||
int opinfo;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
expressionS exp;
|
||||
};
|
||||
|
||||
#define MAX_FIXUPS 5
|
||||
|
||||
static struct fixup fixups[MAX_FIXUPS];
|
||||
static int num_fixups;
|
||||
static struct fixup fixups [MAX_FIXUPS];
|
||||
static int num_fixups;
|
||||
|
||||
/* Prepare to parse an instruction.
|
||||
??? May wish to make this static and delete calls in md_assemble. */
|
||||
@@ -75,16 +75,16 @@ cgen_asm_init_parse ()
|
||||
|
||||
void
|
||||
cgen_queue_fixup (opindex, opinfo, expP)
|
||||
int opindex;
|
||||
expressionS *expP;
|
||||
int opindex;
|
||||
expressionS * expP;
|
||||
{
|
||||
/* We need to generate a fixup for this expression. */
|
||||
if (num_fixups >= MAX_FIXUPS)
|
||||
as_fatal ("too many fixups");
|
||||
fixups[num_fixups].exp = *expP;
|
||||
fixups[num_fixups].exp = * expP;
|
||||
fixups[num_fixups].opindex = opindex;
|
||||
fixups[num_fixups].opinfo = opinfo;
|
||||
++num_fixups;
|
||||
fixups[num_fixups].opinfo = opinfo;
|
||||
++ num_fixups;
|
||||
}
|
||||
|
||||
/* Default routine to record a fixup.
|
||||
@@ -102,16 +102,16 @@ cgen_queue_fixup (opindex, opinfo, expP)
|
||||
|
||||
fixS *
|
||||
cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
|
||||
fragS *frag;
|
||||
int where;
|
||||
const CGEN_INSN *insn;
|
||||
int length;
|
||||
const CGEN_OPERAND *operand;
|
||||
int opinfo;
|
||||
symbolS *symbol;
|
||||
offsetT offset;
|
||||
fragS * frag;
|
||||
int where;
|
||||
const CGEN_INSN * insn;
|
||||
int length;
|
||||
const CGEN_OPERAND * operand;
|
||||
int opinfo;
|
||||
symbolS * symbol;
|
||||
offsetT offset;
|
||||
{
|
||||
fixS *fixP;
|
||||
fixS * fixP;
|
||||
|
||||
/* It may seem strange to use operand->attrs and not insn->attrs here,
|
||||
but it is the operand that has a pc relative relocation. */
|
||||
@@ -119,7 +119,7 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
|
||||
fixP = fix_new (frag, where, length / 8, symbol, offset,
|
||||
CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0,
|
||||
(bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand)));
|
||||
fixP->tc_fix_data.insn = (PTR) insn;
|
||||
fixP->tc_fix_data.insn = (PTR) insn;
|
||||
fixP->tc_fix_data.opinfo = opinfo;
|
||||
|
||||
return fixP;
|
||||
@@ -140,15 +140,15 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset)
|
||||
|
||||
fixS *
|
||||
cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp)
|
||||
fragS *frag;
|
||||
int where;
|
||||
const CGEN_INSN *insn;
|
||||
int length;
|
||||
const CGEN_OPERAND *operand;
|
||||
int opinfo;
|
||||
expressionS *exp;
|
||||
fragS * frag;
|
||||
int where;
|
||||
const CGEN_INSN * insn;
|
||||
int length;
|
||||
const CGEN_OPERAND * operand;
|
||||
int opinfo;
|
||||
expressionS * exp;
|
||||
{
|
||||
fixS *fixP;
|
||||
fixS * fixP;
|
||||
|
||||
/* It may seem strange to use operand->attrs and not insn->attrs here,
|
||||
but it is the operand that has a pc relative relocation. */
|
||||
@@ -178,23 +178,23 @@ static jmp_buf expr_jmp_buf;
|
||||
|
||||
const char *
|
||||
cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
|
||||
enum cgen_parse_operand_type want;
|
||||
const char **strP;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
enum cgen_parse_operand_result *resultP;
|
||||
bfd_vma *valueP;
|
||||
enum cgen_parse_operand_type want;
|
||||
const char ** strP;
|
||||
int opindex;
|
||||
int opinfo;
|
||||
enum cgen_parse_operand_result * resultP;
|
||||
bfd_vma * valueP;
|
||||
{
|
||||
#ifdef __STDC__
|
||||
/* These is volatile to survive the setjmp. */
|
||||
char * volatile hold;
|
||||
char * volatile hold;
|
||||
enum cgen_parse_operand_result * volatile resultP_1;
|
||||
#else
|
||||
static char *hold;
|
||||
static enum cgen_parse_operand_result *resultP_1;
|
||||
static char * hold;
|
||||
static enum cgen_parse_operand_result * resultP_1;
|
||||
#endif
|
||||
const char *errmsg = NULL;
|
||||
expressionS exp;
|
||||
const char * errmsg = NULL;
|
||||
expressionS exp;
|
||||
|
||||
if (want == CGEN_PARSE_OPERAND_INIT)
|
||||
{
|
||||
@@ -204,20 +204,20 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
|
||||
|
||||
resultP_1 = resultP;
|
||||
hold = input_line_pointer;
|
||||
input_line_pointer = (char *) *strP;
|
||||
input_line_pointer = (char *) * strP;
|
||||
|
||||
/* We rely on md_operand to longjmp back to us.
|
||||
This is done via cgen_md_operand. */
|
||||
if (setjmp (expr_jmp_buf) != 0)
|
||||
{
|
||||
input_line_pointer = (char *) hold;
|
||||
*resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
* resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
return "illegal operand";
|
||||
}
|
||||
|
||||
expression (&exp);
|
||||
expression (& exp);
|
||||
|
||||
*strP = input_line_pointer;
|
||||
* strP = input_line_pointer;
|
||||
input_line_pointer = hold;
|
||||
|
||||
/* FIXME: Need to check `want'. */
|
||||
@@ -226,24 +226,24 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
|
||||
{
|
||||
case O_illegal :
|
||||
errmsg = "illegal operand";
|
||||
*resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
* resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
break;
|
||||
case O_absent :
|
||||
errmsg = "missing operand";
|
||||
*resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
* resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
|
||||
break;
|
||||
case O_constant :
|
||||
*valueP = exp.X_add_number;
|
||||
*resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
|
||||
* valueP = exp.X_add_number;
|
||||
* resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
|
||||
break;
|
||||
case O_register :
|
||||
*valueP = exp.X_add_number;
|
||||
*resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
|
||||
* valueP = exp.X_add_number;
|
||||
* resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
|
||||
break;
|
||||
default :
|
||||
cgen_queue_fixup (opindex, opinfo, &exp);
|
||||
*valueP = 0;
|
||||
*resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
|
||||
cgen_queue_fixup (opindex, opinfo, & exp);
|
||||
* valueP = 0;
|
||||
* resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -257,7 +257,7 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP)
|
||||
|
||||
void
|
||||
cgen_md_operand (expressionP)
|
||||
expressionS *expressionP;
|
||||
expressionS * expressionP;
|
||||
{
|
||||
longjmp (expr_jmp_buf, 1);
|
||||
}
|
||||
@@ -268,12 +268,13 @@ cgen_md_operand (expressionP)
|
||||
|
||||
void
|
||||
cgen_asm_finish_insn (insn, buf, length)
|
||||
const CGEN_INSN *insn;
|
||||
cgen_insn_t *buf;
|
||||
unsigned int length;
|
||||
const CGEN_INSN * insn;
|
||||
cgen_insn_t * buf;
|
||||
unsigned int length;
|
||||
{
|
||||
int i, relax_operand;
|
||||
char *f;
|
||||
int i;
|
||||
int relax_operand;
|
||||
char * f;
|
||||
unsigned int byte_len = length / 8;
|
||||
|
||||
/* ??? Target foo issues various warnings here, so one might want to provide
|
||||
@@ -299,7 +300,7 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
/* Scan the fixups for the operand affected by relaxing
|
||||
(i.e. the branch address). */
|
||||
|
||||
for (i = 0; i < num_fixups; ++i)
|
||||
for (i = 0; i < num_fixups; ++ i)
|
||||
{
|
||||
if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex],
|
||||
CGEN_OPERAND_RELAX) != 0)
|
||||
@@ -312,8 +313,8 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
|
||||
if (relax_operand != -1)
|
||||
{
|
||||
int max_len;
|
||||
fragS *old_frag;
|
||||
int max_len;
|
||||
fragS * old_frag;
|
||||
|
||||
#ifdef TC_CGEN_MAX_RELAX
|
||||
max_len = TC_CGEN_MAX_RELAX (insn, byte_len);
|
||||
@@ -323,10 +324,13 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
/* Ensure variable part and fixed part are in same fragment. */
|
||||
/* FIXME: Having to do this seems like a hack. */
|
||||
frag_grow (max_len);
|
||||
|
||||
/* Allocate space for the fixed part. */
|
||||
f = frag_more (byte_len);
|
||||
|
||||
/* Create a relaxable fragment for this instruction. */
|
||||
old_frag = frag_now;
|
||||
|
||||
frag_var (rs_machine_dependent,
|
||||
max_len - byte_len /* max chars */,
|
||||
0 /* variable part already allocated */,
|
||||
@@ -336,11 +340,12 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
fixups[relax_operand].exp.X_add_symbol,
|
||||
fixups[relax_operand].exp.X_add_number,
|
||||
f);
|
||||
|
||||
/* Record the operand number with the fragment so md_convert_frag
|
||||
can use cgen_md_record_fixup to record the appropriate reloc. */
|
||||
old_frag->fr_cgen.insn = insn;
|
||||
old_frag->fr_cgen.insn = insn;
|
||||
old_frag->fr_cgen.opindex = fixups[relax_operand].opindex;
|
||||
old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
|
||||
old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo;
|
||||
}
|
||||
else
|
||||
f = frag_more (byte_len);
|
||||
@@ -352,15 +357,15 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
{
|
||||
case 16:
|
||||
if (cgen_big_endian_p)
|
||||
bfd_putb16 ((bfd_vma) *buf, f);
|
||||
bfd_putb16 ((bfd_vma) * buf, f);
|
||||
else
|
||||
bfd_putl16 ((bfd_vma) *buf, f);
|
||||
bfd_putl16 ((bfd_vma) * buf, f);
|
||||
break;
|
||||
case 32:
|
||||
if (cgen_big_endian_p)
|
||||
bfd_putb32 ((bfd_vma) *buf, f);
|
||||
bfd_putb32 ((bfd_vma) * buf, f);
|
||||
else
|
||||
bfd_putl32 ((bfd_vma) *buf, f);
|
||||
bfd_putl32 ((bfd_vma) * buf, f);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
@@ -388,7 +393,7 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
insn, length,
|
||||
& CGEN_SYM (operand_table) [fixups[i].opindex],
|
||||
fixups[i].opinfo,
|
||||
&fixups[i].exp);
|
||||
& fixups[i].exp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,12 +411,12 @@ cgen_asm_finish_insn (insn, buf, length)
|
||||
|
||||
int
|
||||
cgen_md_apply_fix3 (fixP, valueP, seg)
|
||||
fixS *fixP;
|
||||
valueT *valueP;
|
||||
segT seg;
|
||||
fixS * fixP;
|
||||
valueT * valueP;
|
||||
segT seg;
|
||||
{
|
||||
char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
||||
valueT value;
|
||||
char * where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
||||
valueT value;
|
||||
|
||||
/* FIXME FIXME FIXME: The value we are passed in *valuep includes
|
||||
the symbol values. Since we are using BFD_ASSEMBLER, if we are
|
||||
@@ -426,11 +431,11 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
|
||||
|
||||
if (fixP->fx_addsy == (symbolS *) NULL)
|
||||
{
|
||||
value = *valueP;
|
||||
value = * valueP;
|
||||
fixP->fx_done = 1;
|
||||
}
|
||||
else if (fixP->fx_pcrel)
|
||||
value = *valueP;
|
||||
value = * valueP;
|
||||
else
|
||||
{
|
||||
value = fixP->fx_offset;
|
||||
@@ -449,12 +454,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
|
||||
|
||||
if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
|
||||
{
|
||||
int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
|
||||
const CGEN_OPERAND *operand = & CGEN_SYM (operand_table) [opindex];
|
||||
const char *errmsg;
|
||||
int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
|
||||
const CGEN_OPERAND * operand = & CGEN_SYM (operand_table) [opindex];
|
||||
const char * errmsg;
|
||||
bfd_reloc_code_real_type reloc_type;
|
||||
CGEN_FIELDS fields;
|
||||
const CGEN_INSN *insn = (CGEN_INSN *) fixP->tc_fix_data.insn;
|
||||
CGEN_FIELDS fields;
|
||||
const CGEN_INSN * insn = (CGEN_INSN *) fixP->tc_fix_data.insn;
|
||||
|
||||
/* If the reloc has been fully resolved finish the operand here. */
|
||||
/* FIXME: This duplicates the capabilities of code in BFD. */
|
||||
@@ -465,12 +470,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
|
||||
{
|
||||
/* This may seem like overkill, and using bfd_install_relocation or
|
||||
some such may be preferable, but this is simple. */
|
||||
CGEN_FIELDS_BITSIZE (&fields) = CGEN_INSN_BITSIZE (insn);
|
||||
CGEN_SYM (set_operand) (opindex, &value, &fields);
|
||||
errmsg = CGEN_SYM (validate_operand) (opindex, &fields);
|
||||
CGEN_FIELDS_BITSIZE (& fields) = CGEN_INSN_BITSIZE (insn);
|
||||
CGEN_SYM (set_operand) (opindex, & value, & fields);
|
||||
errmsg = CGEN_SYM (validate_operand) (opindex, & fields);
|
||||
if (errmsg)
|
||||
as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg);
|
||||
CGEN_SYM (insert_operand) (opindex, &fields, where);
|
||||
CGEN_SYM (insert_operand) (opindex, & fields, where);
|
||||
}
|
||||
|
||||
if (fixP->fx_done)
|
||||
@@ -533,10 +538,10 @@ cgen_md_apply_fix3 (fixP, valueP, seg)
|
||||
|
||||
arelent *
|
||||
cgen_tc_gen_reloc (section, fixP)
|
||||
asection *section;
|
||||
fixS *fixP;
|
||||
asection * section;
|
||||
fixS * fixP;
|
||||
{
|
||||
arelent *reloc;
|
||||
arelent * reloc;
|
||||
|
||||
reloc = (arelent *) bfd_alloc (stdoutput, sizeof (arelent));
|
||||
|
||||
@@ -551,9 +556,9 @@ cgen_tc_gen_reloc (section, fixP)
|
||||
|
||||
assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
|
||||
|
||||
reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
|
||||
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
|
||||
reloc->addend = fixP->fx_addnumber;
|
||||
reloc->sym_ptr_ptr = & fixP->fx_addsy->bsym;
|
||||
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
|
||||
reloc->addend = fixP->fx_addnumber;
|
||||
|
||||
return reloc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user