Add support for parallel instructions.

This commit is contained in:
Nick Clifton
1998-01-15 01:58:34 +00:00
parent df5b318730
commit ebde3f6235
3 changed files with 429 additions and 228 deletions

View File

@@ -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;
}