Commit b6fb257b by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Add 'aux' variable attribute.

The 'aux' variable attribute is used to directly access the auxiliary
register space from C.

gcc/
2018-01-31  Claudiu Zissulescu  <claziss@synopsys.com>

        * config/arc/arc.c (arc_handle_aux_attribute): New function.
        (arc_attribute_table): Add 'aux' attribute.
        (arc_in_small_data_p): Consider aux like variables.
        (arc_is_aux_reg_p): New function.
        (arc_asm_output_aligned_decl_local): Ignore 'aux' like variables.
        (arc_get_aux_arg): New function.
        (prepare_move_operands): Handle aux-register access.
        (arc_handle_aux_attribute): New function.
        * doc/extend.texi (ARC Variable attributes): Add subsection.

testsuite/
2018-01-31  Claudiu Zissulescu  <claziss@synopsys.com>

        * gcc.target/arc/taux-1.c: New test.
        * gcc.target/arc/taux-2.c: Likewise.

From-SVN: r257223
parent 8180c03f
2018-01-31 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc.c (arc_handle_aux_attribute): New function.
(arc_attribute_table): Add 'aux' attribute.
(arc_in_small_data_p): Consider aux like variables.
(arc_is_aux_reg_p): New function.
(arc_asm_output_aligned_decl_local): Ignore 'aux' like variables.
(arc_get_aux_arg): New function.
(prepare_move_operands): Handle aux-register access.
(arc_handle_aux_attribute): New function.
* doc/extend.texi (ARC Variable attributes): Add subsection.
2018-01-31 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-protos.h (arc_is_uncached_mem_p): Function proto.
* config/arc/arc.c (arc_handle_uncached_attribute): New function.
(arc_attribute_table): Add 'uncached' attribute.
......
......@@ -228,6 +228,7 @@ static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_jli_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_secure_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_uncached_attribute (tree *, tree, tree, int, bool *);
static tree arc_handle_aux_attribute (tree *, tree, tree, int, bool *);
/* Initialized arc_attribute_table to NULL since arc doesnot have any
machine specific supported attributes. */
......@@ -264,6 +265,7 @@ const struct attribute_spec arc_attribute_table[] =
/* Bypass caches using .di flag. */
{ "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute,
NULL },
{ "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
static int arc_comp_type_attributes (const_tree, const_tree);
......@@ -8135,6 +8137,11 @@ arc_in_small_data_p (const_tree decl)
if (lookup_attribute ("uncached", attr))
return false;
/* and for aux regs. */
attr = DECL_ATTRIBUTES (decl);
if (lookup_attribute ("aux", attr))
return false;
if (DECL_SECTION_NAME (decl) != 0)
{
const char *name = DECL_SECTION_NAME (decl);
......@@ -8302,6 +8309,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode, bool short_p)
return false;
}
/* Return TRUE if PAT is accessing an aux-reg. */
static bool
arc_is_aux_reg_p (rtx pat)
{
tree attrs = NULL_TREE;
tree addr;
if (!MEM_P (pat))
return false;
/* Get the memory attributes. */
addr = MEM_EXPR (pat);
if (!addr)
return false;
/* Get the attributes. */
if (TREE_CODE (addr) == VAR_DECL)
attrs = DECL_ATTRIBUTES (addr);
else if (TREE_CODE (addr) == MEM_REF)
attrs = TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr, 0)));
else
return false;
if (lookup_attribute ("aux", attrs))
return true;
return false;
}
/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
void
......@@ -8310,7 +8346,14 @@ arc_asm_output_aligned_decl_local (FILE * stream, tree decl, const char * name,
unsigned HOST_WIDE_INT align,
unsigned HOST_WIDE_INT globalize_p)
{
int in_small_data = arc_in_small_data_p (decl);
int in_small_data = arc_in_small_data_p (decl);
rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
/* Don't output aux-reg symbols. */
if (mem != NULL_RTX && MEM_P (mem)
&& SYMBOL_REF_P (XEXP (mem, 0))
&& arc_is_aux_reg_p (mem))
return;
if (in_small_data)
switch_to_section (get_named_section (NULL, ".sbss", 0));
......@@ -8650,12 +8693,80 @@ arc_expand_movmem (rtx *operands)
return true;
}
static bool
arc_get_aux_arg (rtx pat, int *auxr)
{
tree attr, addr = MEM_EXPR (pat);
if (TREE_CODE (addr) != VAR_DECL)
return false;
attr = DECL_ATTRIBUTES (addr);
if (lookup_attribute ("aux", attr))
{
tree arg = TREE_VALUE (attr);
if (arg)
{
*auxr = TREE_INT_CST_LOW (TREE_VALUE (arg));
return true;
}
}
return false;
}
/* Prepare operands for move in MODE. Return true iff the move has
been emitted. */
bool
prepare_move_operands (rtx *operands, machine_mode mode)
{
/* First handle aux attribute. */
if (mode == SImode
&& (MEM_P (operands[0]) || MEM_P (operands[1])))
{
rtx tmp;
int auxr = 0;
if (MEM_P (operands[0]) && arc_is_aux_reg_p (operands[0]))
{
/* Save operation. */
if (arc_get_aux_arg (operands[0], &auxr))
{
tmp = gen_reg_rtx (SImode);
emit_move_insn (tmp, GEN_INT (auxr));
}
else
{
tmp = XEXP (operands[0], 0);
}
operands[1] = force_reg (SImode, operands[1]);
emit_insn (gen_rtx_UNSPEC_VOLATILE
(VOIDmode, gen_rtvec (2, operands[1], tmp),
VUNSPEC_ARC_SR));
return true;
}
if (MEM_P (operands[1]) && arc_is_aux_reg_p (operands[1]))
{
if (arc_get_aux_arg (operands[1], &auxr))
{
tmp = gen_reg_rtx (SImode);
emit_move_insn (tmp, GEN_INT (auxr));
}
else
{
tmp = XEXP (operands[1], 0);
gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
}
/* Load operation. */
gcc_assert (REG_P (operands[0]));
emit_insn (gen_rtx_SET (operands[0],
gen_rtx_UNSPEC_VOLATILE
(SImode, gen_rtvec (1, tmp),
VUNSPEC_ARC_LR)));
return true;
}
}
/* We used to do this only for MODE_INT Modes, but addresses to floating
point variables may well be in the small data section. */
if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
......@@ -11191,6 +11302,52 @@ arc_is_uncached_mem_p (rtx pat)
return false;
}
/* Handle aux attribute. The auxiliary registers are addressed using
special instructions lr and sr. The attribute 'aux' indicates if a
variable refers to the aux-regs and what is the register number
desired. */
static tree
arc_handle_aux_attribute (tree *node,
tree name, tree args, int,
bool *no_add_attrs)
{
/* Isn't it better to use address spaces for the aux-regs? */
if (DECL_P (*node))
{
if (TREE_CODE (*node) != VAR_DECL)
{
error ("%qE attribute only applies to variables", name);
*no_add_attrs = true;
}
else if (args)
{
if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
tree arg = TREE_VALUE (args);
if (TREE_CODE (arg) != INTEGER_CST)
{
warning (0, "%qE attribute allows only an integer "
"constant argument", name);
*no_add_attrs = true;
}
/* FIXME! add range check. TREE_INT_CST_LOW (arg) */
}
if (TREE_CODE (*node) == VAR_DECL)
{
tree fntype = TREE_TYPE (*node);
if (fntype && TREE_CODE (fntype) == POINTER_TYPE)
{
tree attrs = tree_cons (get_identifier ("aux"), NULL_TREE,
TYPE_ATTRIBUTES (fntype));
TYPE_ATTRIBUTES (fntype) = attrs;
}
}
}
return NULL_TREE;
}
/* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P. We don't want to use
anchors for small data: the GP register acts as an anchor in that
case. We also don't want to use them for PC-relative accesses,
......
......@@ -5894,6 +5894,7 @@ attributes.
@menu
* Common Variable Attributes::
* ARC Variable Attributes::
* AVR Variable Attributes::
* Blackfin Variable Attributes::
* H8/300 Variable Attributes::
......@@ -6267,6 +6268,18 @@ The @code{weak} attribute is described in
@end table
@node ARC Variable Attributes
@subsection ARC Variable Attributes
@table @code
@item aux
@cindex @code{aux} variable attribute, ARC
The @code{aux} attribute is used to directly access the ARC's
auxiliary register space from C. The auxilirary register number is
given via attribute argument.
@end table
@node AVR Variable Attributes
@subsection AVR Variable Attributes
......
2018-01-31 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/taux-1.c: New test.
* gcc.target/arc/taux-2.c: Likewise.
2018-01-31 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/uncached.c: New test.
2018-01-31 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
......
/* { dg-do compile } */
/* { dg-options "-O1 */
#define __aux() __attribute__((aux))
__aux() int *a_ptr;
extern __aux() int a_var;
/* Generates:
mov r0, @a_var
sr 10,[r0]
*/
void foo (void)
{
a_var = 10;
}
/* Generates:
mov r0, @a_ptr
sr a_var,[r0]
*/
void foo1 (void)
{
a_ptr = &a_var;
}
/* Generates:
lr %r1,[a_ptr]
sr 10,[%r1]
*/
void foo2 (void)
{
*a_ptr = 10;
}
/* { dg-final { scan-assembler-times "sr" 3 } } */
/* { dg-final { scan-assembler-times "lr" 1 } } */
/* { dg-do compile } */
/* { dg-options "-O1 */
#define __aux(r) __attribute__((aux(r)))
static volatile __aux(0x1000) int var;
int foo (void)
{
var++;
}
/* { dg-final { scan-assembler-times "sr" 1 } } */
/* { dg-final { scan-assembler-times "lr" 1 } } */
/* { dg-final { scan-assembler "4096" } } */
/* { dg-final { scan-assembler-not "\\.type\tvar, @object" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment