tm.texi.in (OVERLAPPING_REGISTER_NAMES): Document new macro.

* tm.texi.in (OVERLAPPING_REGISTER_NAMES): Document new macro.
	* tm.texi: Regenerated.
	* output.h (decode_reg_name_and_count): Declare.
	* varasm.c (decode_reg_name_and_count): New function.
	(decode_reg_name): Reimplement using decode_reg_name_and_count.
	* reginfo.c (fix_register): Use decode_reg_name_and_count and 
	iterate over all regs used.
	* stmt.c (expand_asm_operands): Likewise.
	* arm/aout.h (OVERLAPPING_REGISTER_NAMES): Define.
	(ADDITIONAL_REGISTER_NAMES): Remove aliases that overlap
	multiple machine registers.

From-SVN: r166722
This commit is contained in:
Richard Earnshaw 2010-11-13 23:04:26 +00:00 committed by Richard Earnshaw
parent 985c87c94e
commit 0c6d290e6d
8 changed files with 210 additions and 92 deletions

View File

@ -1,3 +1,17 @@
2010-11-13 Richard Earnshaw <rearnsha@arm.com>
* tm.texi.in (OVERLAPPING_REGISTER_NAMES): Document new macro.
* tm.texi: Regenerated.
* output.h (decode_reg_name_and_count): Declare.
* varasm.c (decode_reg_name_and_count): New function.
(decode_reg_name): Reimplement using decode_reg_name_and_count.
* reginfo.c (fix_register): Use decode_reg_name_and_count and
iterate over all regs used.
* stmt.c (expand_asm_operands): Likewise.
* arm/aout.h (OVERLAPPING_REGISTER_NAMES): Define.
(ADDITIONAL_REGISTER_NAMES): Remove aliases that overlap
multiple machine registers.
2010-11-13 Eric Botcazou <ebotcazou@adacore.com>
* stor-layout.c (place_union_field): Do not put location information

View File

@ -163,31 +163,45 @@
{"mvdx12", 39}, \
{"mvdx13", 40}, \
{"mvdx14", 41}, \
{"mvdx15", 42}, \
{"d0", 63}, {"q0", 63}, \
{"d1", 65}, \
{"d2", 67}, {"q1", 67}, \
{"d3", 69}, \
{"d4", 71}, {"q2", 71}, \
{"d5", 73}, \
{"d6", 75}, {"q3", 75}, \
{"d7", 77}, \
{"d8", 79}, {"q4", 79}, \
{"d9", 81}, \
{"d10", 83}, {"q5", 83}, \
{"d11", 85}, \
{"d12", 87}, {"q6", 87}, \
{"d13", 89}, \
{"d14", 91}, {"q7", 91}, \
{"d15", 93}, \
{"q8", 95}, \
{"q9", 99}, \
{"q10", 103}, \
{"q11", 107}, \
{"q12", 111}, \
{"q13", 115}, \
{"q14", 119}, \
{"q15", 123} \
{"mvdx15", 42} \
}
#endif
#ifndef OVERLAPPING_REGISTER_NAMES
#define OVERLAPPING_REGISTER_NAMES \
{ \
{"d0", 63, 2}, \
{"d1", 65, 2}, \
{"d2", 67, 2}, \
{"d3", 69, 2}, \
{"d4", 71, 2}, \
{"d5", 73, 2}, \
{"d6", 75, 2}, \
{"d7", 77, 2}, \
{"d8", 79, 2}, \
{"d9", 81, 2}, \
{"d10", 83, 2}, \
{"d11", 85, 2}, \
{"d12", 87, 2}, \
{"d13", 89, 2}, \
{"d14", 91, 2}, \
{"d15", 93, 2}, \
{"q0", 63, 4}, \
{"q1", 67, 4}, \
{"q2", 71, 4}, \
{"q3", 75, 4}, \
{"q4", 79, 4}, \
{"q5", 83, 4}, \
{"q6", 87, 4}, \
{"q7", 91, 4}, \
{"q8", 95, 4}, \
{"q9", 99, 4}, \
{"q10", 103, 4}, \
{"q11", 107, 4}, \
{"q12", 111, 4}, \
{"q13", 115, 4}, \
{"q14", 119, 4}, \
{"q15", 123, 4} \
}
#endif

View File

@ -8479,6 +8479,22 @@ registers, thus allowing the @code{asm} option in declarations to refer
to registers using alternate names.
@end defmac
@defmac OVERLAPPING_REGISTER_NAMES
If defined, a C initializer for an array of structures containing a
name, a register number and a count of the number of consecutive
machine registers the name overlaps. This macro defines additional
names for hard registers, thus allowing the @code{asm} option in
declarations to refer to registers using alternate names. Unlike
@code{ADDITIONAL_REGISTER_NAMES}, this macro should be used when the
register name implies multiple underlying registers.
This macro should be used when it is important that a clobber in an
@code{asm} statement clobbers all the underlying values implied by the
register name. For example, on ARM, clobbering the double-precision
VFP register ``d0'' implies clobbering both single-precision registers
``s0'' and ``s1''.
@end defmac
@defmac ASM_OUTPUT_OPCODE (@var{stream}, @var{ptr})
Define this macro if you are using an unusual assembler that
requires different names for the machine instructions.

View File

@ -8453,6 +8453,22 @@ registers, thus allowing the @code{asm} option in declarations to refer
to registers using alternate names.
@end defmac
@defmac OVERLAPPING_REGISTER_NAMES
If defined, a C initializer for an array of structures containing a
name, a register number and a count of the number of consecutive
machine registers the name overlaps. This macro defines additional
names for hard registers, thus allowing the @code{asm} option in
declarations to refer to registers using alternate names. Unlike
@code{ADDITIONAL_REGISTER_NAMES}, this macro should be used when the
register name implies multiple underlying registers.
This macro should be used when it is important that a clobber in an
@code{asm} statement clobbers all the underlying values implied by the
register name. For example, on ARM, clobbering the double-precision
VFP register ``d0'' implies clobbering both single-precision registers
``s0'' and ``s1''.
@end defmac
@defmac ASM_OUTPUT_OPCODE (@var{stream}, @var{ptr})
Define this macro if you are using an unusual assembler that
requires different names for the machine instructions.

View File

@ -177,6 +177,11 @@ extern enum tls_model decl_default_tls_model (const_tree);
Prefixes such as % are optional. */
extern int decode_reg_name (const char *);
/* Similar to decode_reg_name, but takes an extra parameter that is a
pointer to the number of (internal) registers described by the
external name. */
extern int decode_reg_name_and_count (const char *, int *);
extern void assemble_alias (tree, tree);
extern void default_assemble_visibility (tree, int);

View File

@ -755,64 +755,69 @@ void
fix_register (const char *name, int fixed, int call_used)
{
int i;
int reg, nregs;
/* Decode the name and update the primary form of
the register info. */
if ((i = decode_reg_name (name)) >= 0)
if ((reg = decode_reg_name_and_count (name, &nregs)) >= 0)
{
if ((i == STACK_POINTER_REGNUM
gcc_assert (nregs >= 1);
for (i = reg; i < reg + nregs; i++)
{
if ((i == STACK_POINTER_REGNUM
#ifdef HARD_FRAME_POINTER_REGNUM
|| i == HARD_FRAME_POINTER_REGNUM
|| i == HARD_FRAME_POINTER_REGNUM
#else
|| i == FRAME_POINTER_REGNUM
|| i == FRAME_POINTER_REGNUM
#endif
)
&& (fixed == 0 || call_used == 0))
{
switch (fixed)
)
&& (fixed == 0 || call_used == 0))
{
case 0:
switch (call_used)
switch (fixed)
{
case 0:
error ("can%'t use %qs as a call-saved register", name);
switch (call_used)
{
case 0:
error ("can%'t use %qs as a call-saved register", name);
break;
case 1:
error ("can%'t use %qs as a call-used register", name);
break;
default:
gcc_unreachable ();
}
break;
case 1:
error ("can%'t use %qs as a call-used register", name);
switch (call_used)
{
case 1:
error ("can%'t use %qs as a fixed register", name);
break;
case 0:
default:
gcc_unreachable ();
}
break;
default:
gcc_unreachable ();
}
break;
case 1:
switch (call_used)
{
case 1:
error ("can%'t use %qs as a fixed register", name);
break;
case 0:
default:
gcc_unreachable ();
}
break;
default:
gcc_unreachable ();
}
}
else
{
fixed_regs[i] = fixed;
call_used_regs[i] = call_used;
else
{
fixed_regs[i] = fixed;
call_used_regs[i] = call_used;
#ifdef CALL_REALLY_USED_REGISTERS
if (fixed == 0)
call_really_used_regs[i] = call_used;
if (fixed == 0)
call_really_used_regs[i] = call_used;
#endif
}
}
}
else

View File

@ -687,13 +687,14 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
{
const char *regname;
int nregs;
if (TREE_VALUE (tail) == error_mark_node)
return;
regname = TREE_STRING_POINTER (TREE_VALUE (tail));
i = decode_reg_name (regname);
if (i >= 0 || i == -4)
i = decode_reg_name_and_count (regname, &nregs);
if (i == -4)
++nclobbers;
else if (i == -2)
error ("unknown register name %qs in %<asm%>", regname);
@ -701,14 +702,21 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
/* Mark clobbered registers. */
if (i >= 0)
{
/* Clobbering the PIC register is an error. */
if (i == (int) PIC_OFFSET_TABLE_REGNUM)
{
error ("PIC register %qs clobbered in %<asm%>", regname);
return;
}
int reg;
SET_HARD_REG_BIT (clobbered_regs, i);
for (reg = i; reg < i + nregs; reg++)
{
++nclobbers;
/* Clobbering the PIC register is an error. */
if (reg == (int) PIC_OFFSET_TABLE_REGNUM)
{
error ("PIC register clobbered by %qs in %<asm%>", regname);
return;
}
SET_HARD_REG_BIT (clobbered_regs, reg);
}
}
}
@ -1033,7 +1041,8 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
for (tail = clobbers; tail; tail = TREE_CHAIN (tail))
{
const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail));
int j = decode_reg_name (regname);
int reg, nregs;
int j = decode_reg_name_and_count (regname, &nregs);
rtx clobbered_reg;
if (j < 0)
@ -1055,30 +1064,39 @@ expand_asm_operands (tree string, tree outputs, tree inputs,
continue;
}
/* Use QImode since that's guaranteed to clobber just one reg. */
clobbered_reg = gen_rtx_REG (QImode, j);
/* Do sanity check for overlap between clobbers and respectively
input and outputs that hasn't been handled. Such overlap
should have been detected and reported above. */
if (!clobber_conflict_found)
for (reg = j; reg < j + nregs; reg++)
{
int opno;
/* Use QImode since that's guaranteed to clobber just
* one reg. */
clobbered_reg = gen_rtx_REG (QImode, reg);
/* We test the old body (obody) contents to avoid tripping
over the under-construction body. */
for (opno = 0; opno < noutputs; opno++)
if (reg_overlap_mentioned_p (clobbered_reg, output_rtx[opno]))
internal_error ("asm clobber conflict with output operand");
/* Do sanity check for overlap between clobbers and
respectively input and outputs that hasn't been
handled. Such overlap should have been detected and
reported above. */
if (!clobber_conflict_found)
{
int opno;
for (opno = 0; opno < ninputs - ninout; opno++)
if (reg_overlap_mentioned_p (clobbered_reg,
ASM_OPERANDS_INPUT (obody, opno)))
internal_error ("asm clobber conflict with input operand");
/* We test the old body (obody) contents to avoid
tripping over the under-construction body. */
for (opno = 0; opno < noutputs; opno++)
if (reg_overlap_mentioned_p (clobbered_reg,
output_rtx[opno]))
internal_error
("asm clobber conflict with output operand");
for (opno = 0; opno < ninputs - ninout; opno++)
if (reg_overlap_mentioned_p (clobbered_reg,
ASM_OPERANDS_INPUT (obody,
opno)))
internal_error
("asm clobber conflict with input operand");
}
XVECEXP (body, 0, i++)
= gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
}
XVECEXP (body, 0, i++)
= gen_rtx_CLOBBER (VOIDmode, clobbered_reg);
}
if (nlabels > 0)

View File

@ -764,8 +764,11 @@ set_user_assembler_name (tree decl, const char *name)
Prefixes such as % are optional. */
int
decode_reg_name (const char *asmspec)
decode_reg_name_and_count (const char *asmspec, int *pnregs)
{
/* Presume just one register is clobbered. */
*pnregs = 1;
if (asmspec != 0)
{
int i;
@ -791,6 +794,25 @@ decode_reg_name (const char *asmspec)
&& ! strcmp (asmspec, strip_reg_name (reg_names[i])))
return i;
#ifdef OVERLAPPING_REGISTER_NAMES
{
static const struct
{
const char *const name;
const int number;
const int nregs;
} table[] = OVERLAPPING_REGISTER_NAMES;
for (i = 0; i < (int) ARRAY_SIZE (table); i++)
if (table[i].name[0]
&& ! strcmp (asmspec, table[i].name))
{
*pnregs = table[i].nregs;
return table[i].number;
}
}
#endif /* OVERLAPPING_REGISTER_NAMES */
#ifdef ADDITIONAL_REGISTER_NAMES
{
static const struct { const char *const name; const int number; } table[]
@ -814,6 +836,14 @@ decode_reg_name (const char *asmspec)
return -1;
}
int
decode_reg_name (const char *name)
{
int count;
return decode_reg_name_and_count (name, &count);
}
/* Return true if DECL's initializer is suitable for a BSS section. */