* config/tc-rx.c (rx_fetchalign): Declare.

(md_pseudo_table): Add .fetchalign.
(RX_NBASE_FETCHALIGN): New.
(fetchalign_bytes): New.
(rx_fetchalign): New.
(rx_frag_init): If a "magic" value is found, also init the
machine-specific data.
(md_assemble): Note following opcode size if called for.
(rx_next_opcode): New.
(rx_relax_frag): Support .fetchalign.
(md_convert_frag): Likewise.
* doc/c-rx.texi (RX-Directives): Add .fetchalign.
This commit is contained in:
DJ Delorie 2012-05-15 03:04:47 +00:00
parent d051b294b9
commit 0e25bcb440
3 changed files with 121 additions and 3 deletions

View File

@ -1,3 +1,18 @@
2012-05-14 DJ Delorie <dj@redhat.com>
* config/tc-rx.c (rx_fetchalign): Declare.
(md_pseudo_table): Add .fetchalign.
(RX_NBASE_FETCHALIGN): New.
(fetchalign_bytes): New.
(rx_fetchalign): New.
(rx_frag_init): If a "magic" value is found, also init the
machine-specific data.
(md_assemble): Note following opcode size if called for.
(rx_next_opcode): New.
(rx_relax_frag): Support .fetchalign.
(md_convert_frag): Likewise.
* doc/c-rx.texi (RX-Directives): Add .fetchalign.
2012-05-14 James Lemke <jwlemke@codesourcery.com> 2012-05-14 James Lemke <jwlemke@codesourcery.com>
* config/tc-ppc.c (insn_validate): New func of existing code to call.. * config/tc-ppc.c (insn_validate): New func of existing code to call..

View File

@ -56,6 +56,8 @@ static int rx_num_int_regs = 0;
int rx_pid_register; int rx_pid_register;
int rx_gp_register; int rx_gp_register;
static void rx_fetchalign (int ignore ATTRIBUTE_UNUSED);
enum options enum options
{ {
OPTION_BIG = OPTION_MD_BASE, OPTION_BIG = OPTION_MD_BASE,
@ -600,6 +602,8 @@ const pseudo_typeS md_pseudo_table[] =
{ "int", cons, 4 }, { "int", cons, 4 },
{ "word", cons, 4 }, { "word", cons, 4 },
{ "fetchalign", rx_fetchalign, 0 },
/* End of list marker. */ /* End of list marker. */
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
@ -648,9 +652,14 @@ md_begin (void)
char * rx_lex_start; char * rx_lex_start;
char * rx_lex_end; char * rx_lex_end;
/* These negative numbers are found in rx_bytesT.n_base for non-opcode
md_frags */
#define RX_NBASE_FETCHALIGN -1
typedef struct rx_bytesT typedef struct rx_bytesT
{ {
char base[4]; char base[4];
/* If this is negative, it's a special-purpose frag as per the defines above. */
int n_base; int n_base;
char ops[8]; char ops[8];
int n_ops; int n_ops;
@ -678,6 +687,31 @@ typedef struct rx_bytesT
} rx_bytesT; } rx_bytesT;
static rx_bytesT rx_bytes; static rx_bytesT rx_bytes;
/* We set n_ops to be "size of next opcode" if the next opcode doesn't relax. */
static rx_bytesT *fetchalign_bytes = NULL;
static void
rx_fetchalign (int ignore ATTRIBUTE_UNUSED)
{
char * bytes;
fragS * frag_then;
memset (& rx_bytes, 0, sizeof (rx_bytes));
rx_bytes.n_base = RX_NBASE_FETCHALIGN;
bytes = frag_more (8);
frag_then = frag_now;
frag_variant (rs_machine_dependent,
0 /* max_chars */,
0 /* var */,
0 /* subtype */,
0 /* symbol */,
0 /* offset */,
0 /* opcode */);
frag_then->fr_opcode = bytes;
frag_then->fr_subtype = 0;
fetchalign_bytes = frag_then->tc_frag_data;
}
void void
rx_relax (int type, int pos) rx_relax (int type, int pos)
@ -933,7 +967,7 @@ rx_wrap (void)
void void
rx_frag_init (fragS * fragP) rx_frag_init (fragS * fragP)
{ {
if (rx_bytes.n_relax || rx_bytes.link_relax) if (rx_bytes.n_relax || rx_bytes.link_relax || rx_bytes.n_base < 0)
{ {
fragP->tc_frag_data = malloc (sizeof (rx_bytesT)); fragP->tc_frag_data = malloc (sizeof (rx_bytesT));
memcpy (fragP->tc_frag_data, & rx_bytes, sizeof (rx_bytesT)); memcpy (fragP->tc_frag_data, & rx_bytes, sizeof (rx_bytesT));
@ -1049,8 +1083,12 @@ md_assemble (char * str)
{ {
bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops); bytes = frag_more (rx_bytes.n_base + rx_bytes.n_ops);
frag_then = frag_now; frag_then = frag_now;
if (fetchalign_bytes)
fetchalign_bytes->n_ops = rx_bytes.n_base + rx_bytes.n_ops;
} }
fetchalign_bytes = NULL;
APPEND (base, n_base); APPEND (base, n_base);
APPEND (ops, n_ops); APPEND (ops, n_ops);
@ -1413,6 +1451,18 @@ md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED, segT segment ATTR
return delta; return delta;
} }
/* Given a frag FRAGP, return the "next" frag that contains an
opcode. Assumes the next opcode is relaxable, and thus rs_machine_dependent. */
static fragS *
rx_next_opcode (fragS *fragP)
{
do {
fragP = fragP->fr_next;
} while (fragP && fragP->fr_type != rs_machine_dependent);
return fragP;
}
/* Given the new addresses for this relax pass, figure out how big /* Given the new addresses for this relax pass, figure out how big
each opcode must be. We store the total number of bytes needed in each opcode must be. We store the total number of bytes needed in
fr_subtype. The return value is the difference between the size fr_subtype. The return value is the difference between the size
@ -1437,6 +1487,34 @@ rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
(long) fragP->fr_fix, (long) fragP->fr_var, (long) fragP->fr_offset, (long) fragP->fr_fix, (long) fragP->fr_var, (long) fragP->fr_offset,
fragP->fr_literal, fragP->fr_opcode, fragP->fr_type, fragP->fr_subtype, stretch); fragP->fr_literal, fragP->fr_opcode, fragP->fr_type, fragP->fr_subtype, stretch);
mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
if (fragP->tc_frag_data->n_base == RX_NBASE_FETCHALIGN)
{
unsigned int next_size;
if (fragP->fr_next == NULL)
return 0;
next_size = fragP->tc_frag_data->n_ops;
if (next_size == 0)
{
fragS *n = rx_next_opcode (fragP);
next_size = n->fr_subtype;
}
fragP->fr_subtype = (8-(mypc & 7)) & 7;
tprintf("subtype %u\n", fragP->fr_subtype);
if (fragP->fr_subtype >= next_size)
fragP->fr_subtype = 0;
tprintf ("\033[34m -> mypc %lu next_size %u new %d old %d delta %d (fetchalign)\033[0m\n",
mypc & 7,
next_size, fragP->fr_subtype, oldsize, fragP->fr_subtype-oldsize);
newsize = fragP->fr_subtype;
return newsize - oldsize;
}
optype = rx_opcode_type (fragP->fr_opcode); optype = rx_opcode_type (fragP->fr_opcode);
/* In the one case where we have both a disp and imm relaxation, we want /* In the one case where we have both a disp and imm relaxation, we want
@ -1485,7 +1563,6 @@ rx_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
return newsize - oldsize; return newsize - oldsize;
} }
mypc = fragP->fr_address + (fragP->fr_opcode - fragP->fr_literal);
if (sym_addr > mypc) if (sym_addr > mypc)
addr0 += stretch; addr0 += stretch;
@ -1644,13 +1721,29 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
{ {
int i; int i;
printf ("lit %08x opc %08x", (int) fragP->fr_literal, (int) fragP->fr_opcode); printf ("lit 0x%p opc 0x%p", fragP->fr_literal, fragP->fr_opcode);
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
printf (" %02x", (unsigned char) (fragP->fr_opcode[i])); printf (" %02x", (unsigned char) (fragP->fr_opcode[i]));
printf ("\n"); printf ("\n");
} }
#endif #endif
if (fragP->tc_frag_data->n_base == RX_NBASE_FETCHALIGN)
{
int count = fragP->fr_subtype;
if (count == 0)
;
else if (count > BIGGEST_NOP)
{
op[0] = 0x2e;
op[1] = count;
}
else if (count > 0)
{
memcpy (op, nops[count], count);
}
}
/* In the one case where we have both a disp and imm relaxation, we want /* In the one case where we have both a disp and imm relaxation, we want
the imm relaxation here. */ the imm relaxation here. */
ri = 0; ri = 0;

View File

@ -155,6 +155,16 @@ assembler directives:
@cindex RX assembler directive .3byte @cindex RX assembler directive .3byte
Inserts a 3-byte value into the output file at the current location. Inserts a 3-byte value into the output file at the current location.
@item .fetchalign
@cindex assembler directive .fetchalign, RX
@cindex RX assembler directive .fetchalign
If the next opcode following this directive spans a fetch line
boundary (8 byte boundary), the opcode is aligned to that boundary.
If the next opcode does not span a fetch line, this directive has no
effect. Note that one or more labels may be between this directive
and the opcode; those labels are aligned as well. Any inserted bytes
due to alignment will form a NOP opcode.
@end table @end table
@node RX-Float @node RX-Float