From: Claudiu Zissulescu Date: Wed, 31 Jan 2018 10:01:48 +0000 (+0100) Subject: [ARC] Add 'aux' variable attribute. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b6fb257bd6fe6a4d03937a8c3cee6ff4dfa1002a;p=gcc.git [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 * 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 * gcc.target/arc/taux-1.c: New test. * gcc.target/arc/taux-2.c: Likewise. From-SVN: r257223 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0b380db6b52..db2c33536ce 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2018-01-31 Claudiu Zissulescu + + * 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 * config/arc/arc-protos.h (arc_is_uncached_mem_p): Function proto. diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 624404cf35a..843defd4cda 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -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, diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8eef2a492b3..cb9df971a5f 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9056519e8ce..d6bca328096 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-01-31 Claudiu Zissulescu + + * gcc.target/arc/taux-1.c: New test. + * gcc.target/arc/taux-2.c: Likewise. + 2018-01-31 Claudiu Zissulescu * gcc.target/arc/uncached.c: New test. diff --git a/gcc/testsuite/gcc.target/arc/taux-1.c b/gcc/testsuite/gcc.target/arc/taux-1.c new file mode 100644 index 00000000000..a2b77782192 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/taux-1.c @@ -0,0 +1,38 @@ +/* { 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 } } */ diff --git a/gcc/testsuite/gcc.target/arc/taux-2.c b/gcc/testsuite/gcc.target/arc/taux-2.c new file mode 100644 index 00000000000..5644bcd65c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/taux-2.c @@ -0,0 +1,15 @@ +/* { 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" } } */