📄 500-avr32.patch
字号:
+ return NULL_RTX;+ }++ if (!(*insn_data[icode].operand[2].predicate) (op2, SImode))+ {+ error+ ("Parameter 3 to __builtin_cop is not a valid coprocessor register number.");+ error ("Number should be between 0 and 15.");+ return NULL_RTX;+ }++ if (!(*insn_data[icode].operand[3].predicate) (op3, SImode))+ {+ error+ ("Parameter 4 to __builtin_cop is not a valid coprocessor register number.");+ error ("Number should be between 0 and 15.");+ return NULL_RTX;+ }++ if (!(*insn_data[icode].operand[4].predicate) (op4, SImode))+ {+ error+ ("Parameter 5 to __builtin_cop is not a valid coprocessor operation.");+ error ("Number should be between 0 and 127.");+ return NULL_RTX;+ }++ pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);+ if (!pat)+ return 0;+ emit_insn (pat);++ return target;+ }+ }++ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)+ if (d->code == fcode)+ return avr32_expand_binop_builtin (d->icode, arglist, target);+++ /* @@@ Should really do something sensible here. */+ return NULL_RTX;+}+++/* Handle an "interrupt" or "isr" attribute;+ arguments as in struct attribute_spec.handler. */++static tree+avr32_handle_isr_attribute (tree * node, tree name, tree args,+ int flags, bool * no_add_attrs)+{+ if (DECL_P (*node))+ {+ if (TREE_CODE (*node) != FUNCTION_DECL)+ {+ warning ("`%s' attribute only applies to functions",+ IDENTIFIER_POINTER (name));+ *no_add_attrs = true;+ }+ /* FIXME: the argument if any is checked for type attributes; should it+ be checked for decl ones? */+ }+ else+ {+ if (TREE_CODE (*node) == FUNCTION_TYPE+ || TREE_CODE (*node) == METHOD_TYPE)+ {+ if (avr32_isr_value (args) == AVR32_FT_UNKNOWN)+ {+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));+ *no_add_attrs = true;+ }+ }+ else if (TREE_CODE (*node) == POINTER_TYPE+ && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE+ || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)+ && avr32_isr_value (args) != AVR32_FT_UNKNOWN)+ {+ *node = build_variant_type_copy (*node);+ TREE_TYPE (*node) = build_type_attribute_variant+ (TREE_TYPE (*node),+ tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));+ *no_add_attrs = true;+ }+ else+ {+ /* Possibly pass this attribute on from the type to a decl. */+ if (flags & ((int) ATTR_FLAG_DECL_NEXT+ | (int) ATTR_FLAG_FUNCTION_NEXT+ | (int) ATTR_FLAG_ARRAY_NEXT))+ {+ *no_add_attrs = true;+ return tree_cons (name, args, NULL_TREE);+ }+ else+ {+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));+ }+ }+ }++ return NULL_TREE;+}++/* Handle an attribute requiring a FUNCTION_DECL;+ arguments as in struct attribute_spec.handler. */+static tree+avr32_handle_fndecl_attribute (tree * node, tree name,+ tree args ATTRIBUTE_UNUSED,+ int flags ATTRIBUTE_UNUSED,+ bool * no_add_attrs)+{+ if (TREE_CODE (*node) != FUNCTION_DECL)+ {+ warning ("%qs attribute only applies to functions",+ IDENTIFIER_POINTER (name));+ *no_add_attrs = true;+ }++ return NULL_TREE;+}+++/* Handle an acall attribute;+ arguments as in struct attribute_spec.handler. */++static tree+avr32_handle_acall_attribute (tree * node, tree name,+ tree args ATTRIBUTE_UNUSED,+ int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)+{+ if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)+ {+ warning ("`%s' attribute not yet supported...",+ IDENTIFIER_POINTER (name));+ *no_add_attrs = true;+ return NULL_TREE;+ }++ warning ("`%s' attribute only applies to functions",+ IDENTIFIER_POINTER (name));+ *no_add_attrs = true;+ return NULL_TREE;+}+++/* Return 0 if the attributes for two types are incompatible, 1 if they+ are compatible, and 2 if they are nearly compatible (which causes a+ warning to be generated). */++static int+avr32_comp_type_attributes (tree type1, tree type2)+{+ int acall1, acall2, isr1, isr2, naked1, naked2;++ /* Check for mismatch of non-default calling convention. */+ if (TREE_CODE (type1) != FUNCTION_TYPE)+ return 1;++ /* Check for mismatched call attributes. */+ acall1 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type1)) != NULL;+ acall2 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type2)) != NULL;+ naked1 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type1)) != NULL;+ naked2 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type2)) != NULL;+ isr1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;+ if (!isr1)+ isr1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;++ isr2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;+ if (!isr2)+ isr2 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;++ if ((acall1 && isr2)+ || (acall2 && isr1) || (naked1 && isr2) || (naked2 && isr1))+ return 0;++ return 1;+}+++/* Computes the type of the current function. */++static unsigned long+avr32_compute_func_type (void)+{+ unsigned long type = AVR32_FT_UNKNOWN;+ tree a;+ tree attr;++ if (TREE_CODE (current_function_decl) != FUNCTION_DECL)+ abort ();++ /* Decide if the current function is volatile. Such functions never+ return, and many memory cycles can be saved by not storing register+ values that will never be needed again. This optimization was added to+ speed up context switching in a kernel application. */+ if (optimize > 0+ && TREE_NOTHROW (current_function_decl)+ && TREE_THIS_VOLATILE (current_function_decl))+ type |= AVR32_FT_VOLATILE;++ if (cfun->static_chain_decl != NULL)+ type |= AVR32_FT_NESTED;++ attr = DECL_ATTRIBUTES (current_function_decl);++ a = lookup_attribute ("isr", attr);+ if (a == NULL_TREE)+ a = lookup_attribute ("interrupt", attr);++ if (a == NULL_TREE)+ type |= AVR32_FT_NORMAL;+ else+ type |= avr32_isr_value (TREE_VALUE (a));+++ a = lookup_attribute ("acall", attr);+ if (a != NULL_TREE)+ type |= AVR32_FT_ACALL;++ a = lookup_attribute ("naked", attr);+ if (a != NULL_TREE)+ type |= AVR32_FT_NAKED;++ return type;+}++/* Returns the type of the current function. */++static unsigned long+avr32_current_func_type (void)+{+ if (AVR32_FUNC_TYPE (cfun->machine->func_type) == AVR32_FT_UNKNOWN)+ cfun->machine->func_type = avr32_compute_func_type ();++ return cfun->machine->func_type;+}++/*+ This target hook should return true if we should not pass type solely+ in registers. The file expr.h defines a definition that is usually appropriate,+ refer to expr.h for additional documentation.+*/+bool+avr32_must_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)+{+ if (type && AGGREGATE_TYPE_P (type)+ /* If the alignment is less than the size then pass in the struct on+ the stack. */+ && ((unsigned int) TYPE_ALIGN_UNIT (type) <+ (unsigned int) int_size_in_bytes (type))+ /* If we support unaligned word accesses then structs of size 4 and 8+ can have any alignment and still be passed in registers. */+ && !(TARGET_UNALIGNED_WORD+ && (int_size_in_bytes (type) == 4+ || int_size_in_bytes (type) == 8))+ /* Double word structs need only a word alignment. */+ && !(int_size_in_bytes (type) == 8 && TYPE_ALIGN_UNIT (type) >= 4))+ return true;++ if (type && AGGREGATE_TYPE_P (type)+ /* Structs of size 3,5,6,7 are always passed in registers. */+ && (int_size_in_bytes (type) == 3+ || int_size_in_bytes (type) == 5+ || int_size_in_bytes (type) == 6 || int_size_in_bytes (type) == 7))+ return true;+++ return (type && TREE_ADDRESSABLE (type));+}+++bool+avr32_strict_argument_naming (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED)+{+ return true;+}++/*+ This target hook should return true if an argument at the position indicated+ by cum should be passed by reference. This predicate is queried after target+ independent reasons for being passed by reference, such as TREE_ADDRESSABLE (type).++ If the hook returns true, a copy of that argument is made in memory and a+ pointer to the argument is passed instead of the argument itself. The pointer+ is passed in whatever way is appropriate for passing a pointer to that type.+*/+bool+avr32_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,+ enum machine_mode mode ATTRIBUTE_UNUSED,+ tree type, bool named ATTRIBUTE_UNUSED)+{+ return (type && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST));+}++static int+avr32_arg_partial_bytes (CUMULATIVE_ARGS * pcum ATTRIBUTE_UNUSED,+ enum machine_mode mode ATTRIBUTE_UNUSED,+ tree type ATTRIBUTE_UNUSED,+ bool named ATTRIBUTE_UNUSED)+{+ return 0;+}+++struct gcc_target targetm = TARGET_INITIALIZER;++/*+ Table used to convert from register number in the assembler instructions and+ the register numbers used in gcc.+*/+const int avr32_function_arg_reglist[] =+{+ INTERNAL_REGNUM (12),+ INTERNAL_REGNUM (11),+ INTERNAL_REGNUM (10),+ INTERNAL_REGNUM (9),+ INTERNAL_REGNUM (8)+};++rtx avr32_compare_op0 = NULL_RTX;+rtx avr32_compare_op1 = NULL_RTX;+rtx avr32_compare_operator = NULL_RTX;+rtx avr32_acc_cache = NULL_RTX;++/*+ Returns nonzero if it is allowed to store a value of mode mode in hard+ register number regno.+*/+int+avr32_hard_regno_mode_ok (int regnr, enum machine_mode mode)+{+ /* We allow only float modes in the fp-registers */+ if (regnr >= FIRST_FP_REGNUM+ && regnr <= LAST_FP_REGNUM && GET_MODE_CLASS (mode) != MODE_FLOAT)+ {+ return 0;+ }++ switch (mode)+ {+ case DImode: /* long long */+ case DFmode: /* double */+ case SCmode: /* __complex__ float */+ case CSImode: /* __complex__ int */+ if (regnr < 4)+ { /* long long int not supported in r12, sp, lr+ or pc. */+ return 0;+ }+ else+ {+ if (regnr % 2) /* long long int has to be refered in even+ registers. */+ return 0;+ else+ return 1;+ }+ case CDImode: /* __complex__ long long */+ case DCmode: /* __complex__ double */+ case TImode: /* 16 bytes */+ if (regnr < 7)+ return 0;+ else if (regnr % 2)+ return 0;+ else+ return 1;+ default:+ return 1;+ }+}+++int+avr32_rnd_operands (rtx add, rtx shift)+{+ if (GET_CODE (shift) == CONST_INT &&+ GET_CODE (add) == CONST_INT && INTVAL (shift) > 0)+ {+ if ((1 << (INTVAL (shift) - 1)) == INTVAL (add))+ return TRUE;+ }++ return FALSE;+}++++int+avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c, const char *str)+{+ switch (c)+ {+ case 'K':+ case 'I':+ {+ HOST_WIDE_INT min_value = 0, max_value = 0;+ char size_str[3];+ int const_size;++ size_str[0] = str[2];+ size_str[1] = str[3];+ size_str[2] = '\0';+ const_size = atoi (size_str);++ if (toupper (str[1]) == 'U')+ {+ min_value = 0;+ max_value = (1 << const_size) - 1;+ }+ else if (toupp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -