mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 09:40:54 +08:00
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:
parent
985c87c94e
commit
0c6d290e6d
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
78
gcc/stmt.c
78
gcc/stmt.c
@ -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)
|
||||
|
32
gcc/varasm.c
32
gcc/varasm.c
@ -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. */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user