diff options
Diffstat (limited to 'patches/gcc-4.4.3/atmel/0009-Adds-AVR-builtin-functions.patch')
-rw-r--r-- | patches/gcc-4.4.3/atmel/0009-Adds-AVR-builtin-functions.patch | 611 |
1 files changed, 0 insertions, 611 deletions
diff --git a/patches/gcc-4.4.3/atmel/0009-Adds-AVR-builtin-functions.patch b/patches/gcc-4.4.3/atmel/0009-Adds-AVR-builtin-functions.patch deleted file mode 100644 index 8d93cd5..0000000 --- a/patches/gcc-4.4.3/atmel/0009-Adds-AVR-builtin-functions.patch +++ /dev/null @@ -1,611 +0,0 @@ -From 6a39c24ac33a36787b8daa2cb76eda1200b565e4 Mon Sep 17 00:00:00 2001 -From: Stephan Linz <linz@li-pro.net> -Date: Wed, 20 Apr 2011 22:48:45 +0200 -Subject: [PATCH 09/10] Adds AVR builtin functions - -Not yet committed patch written by Anatoly Sokolov and Eric -Weddington. - -Assimilable post by Eric Weddington (2011-03-23): -http://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg01354.html - -Original ATMEL patch from: -http://distribute.atmel.no/tools/opensource/avr-gcc/gcc-4.4.3/61-gcc-4.4.3-builtins-v6.patch - -Signed-off-by: Stephan Linz <linz@li-pro.net> ---- - gcc/config/avr/avr.c | 244 +++++++++++++++++++++++++++++++++++++++++ - gcc/config/avr/avr.md | 248 ++++++++++++++++++++++++++++++++++++++++-- - gcc/config/avr/predicates.md | 5 + - 3 files changed, 485 insertions(+), 12 deletions(-) - -diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c -index 0175fae..edbfd17 100644 ---- a/gcc/config/avr/avr.c -+++ b/gcc/config/avr/avr.c -@@ -30,6 +30,7 @@ - #include "insn-config.h" - #include "conditions.h" - #include "insn-attr.h" -+#include "insn-codes.h" - #include "flags.h" - #include "reload.h" - #include "tree.h" -@@ -39,7 +40,9 @@ - #include "obstack.h" - #include "function.h" - #include "recog.h" -+#include "optabs.h" - #include "ggc.h" -+#include "langhooks.h" - #include "tm_p.h" - #include "target.h" - #include "target-def.h" -@@ -92,6 +95,8 @@ static bool avr_rtx_costs (rtx, int, int, int *, bool); - static int avr_address_cost (rtx, bool); - static bool avr_return_in_memory (const_tree, const_tree); - static struct machine_function * avr_init_machine_status (void); -+static void avr_init_builtins (void); -+static rtx avr_expand_builtin (tree, rtx, rtx, enum machine_mode, int); - static rtx avr_builtin_setjmp_frame_value (void); - static bool avr_hard_regno_scratch_ok (unsigned int); - -@@ -477,6 +482,12 @@ int avr_case_values_threshold = 30000; - #undef TARGET_HARD_REGNO_SCRATCH_OK - #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok - -+#undef TARGET_INIT_BUILTINS -+#define TARGET_INIT_BUILTINS avr_init_builtins -+ -+#undef TARGET_EXPAND_BUILTIN -+#define TARGET_EXPAND_BUILTIN avr_expand_builtin -+ - #undef TARGET_SCALAR_MODE_SUPPORTED_P - #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p - -@@ -7459,4 +7470,237 @@ avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) - return false; - } - -+/* Codes for all the AVR builtins. */ -+ -+enum avr_builtins -+{ -+ AVR_BUILTIN_SEI, -+ AVR_BUILTIN_CLI, -+ AVR_BUILTIN_WDR, -+ AVR_BUILTIN_SLEEP, -+ AVR_BUILTIN_SWAP, -+ AVR_BUILTIN_FMUL, -+ AVR_BUILTIN_FMULS, -+ AVR_BUILTIN_FMULSU, -+ AVR_BUILTIN_DELAY_CYCLES -+}; -+ -+#define def_builtin(NAME, TYPE, CODE) \ -+do { \ -+ add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \ -+ NULL, NULL_TREE); \ -+} while (0) -+ -+/* Set up all builtin functions for this target. */ -+ -+static void -+avr_init_builtins (void) -+{ -+ tree void_ftype_void -+ = build_function_type (void_type_node, void_list_node); -+ tree uchar_ftype_uchar -+ = build_function_type_list (unsigned_char_type_node, -+ unsigned_char_type_node, -+ NULL_TREE); -+ tree uint_ftype_uchar_uchar -+ = build_function_type_list (unsigned_type_node, -+ unsigned_char_type_node, -+ unsigned_char_type_node, -+ NULL_TREE); -+ tree int_ftype_char_char -+ = build_function_type_list (integer_type_node, -+ char_type_node, -+ char_type_node, -+ NULL_TREE); -+ tree int_ftype_char_uchar -+ = build_function_type_list (integer_type_node, -+ char_type_node, -+ unsigned_char_type_node, -+ NULL_TREE); -+ tree void_ftype_ulong -+ = build_function_type_list (void_type_node, -+ long_unsigned_type_node, -+ NULL_TREE); -+ -+ def_builtin ("__builtin_avr_sei", void_ftype_void, AVR_BUILTIN_SEI); -+ def_builtin ("__builtin_avr_cli", void_ftype_void, AVR_BUILTIN_CLI); -+ def_builtin ("__builtin_avr_wdr", void_ftype_void, AVR_BUILTIN_WDR); -+ def_builtin ("__builtin_avr_sleep", void_ftype_void, AVR_BUILTIN_SLEEP); -+ -+ if (AVR_HAVE_MUL) -+ { -+ def_builtin ("__builtin_avr_fmul", uint_ftype_uchar_uchar, -+ AVR_BUILTIN_FMUL); -+ def_builtin ("__builtin_avr_fmuls", int_ftype_char_char, -+ AVR_BUILTIN_FMULS); -+ def_builtin ("__builtin_avr_fmulsu", int_ftype_char_uchar, -+ AVR_BUILTIN_FMULSU); -+ } -+ -+ def_builtin ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP); -+ def_builtin ("__builtin_avr_delay_cycles", void_ftype_ulong, -+ AVR_BUILTIN_DELAY_CYCLES); -+} -+ -+struct builtin_description -+{ -+ const enum insn_code icode; -+ const char *const name; -+ const enum avr_builtins code; -+}; -+ -+static const struct builtin_description bdesc_1arg[] = -+{ -+ { CODE_FOR_swap, "__builtin_avr_swap", AVR_BUILTIN_SWAP } -+}; -+ -+static const struct builtin_description bdesc_2arg[] = -+{ -+ { CODE_FOR_fmul, "__builtin_avr_fmul", AVR_BUILTIN_FMUL }, -+ { CODE_FOR_fmuls, "__builtin_avr_fmuls", AVR_BUILTIN_FMULS }, -+ { CODE_FOR_fmulsu, "__builtin_avr_fmulsu", AVR_BUILTIN_FMULSU } -+}; -+ -+/* Subroutine of avr_expand_builtin to take care of unop insns. */ -+ -+static rtx -+avr_expand_unop_builtin (enum insn_code icode, tree exp, -+ rtx target) -+{ -+ rtx pat; -+ tree arg0 = CALL_EXPR_ARG (exp, 0); -+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); -+ enum machine_mode op0mode = GET_MODE (op0); -+ enum machine_mode tmode = insn_data[icode].operand[0].mode; -+ enum machine_mode mode0 = insn_data[icode].operand[1].mode; -+ -+ if (! target -+ || GET_MODE (target) != tmode -+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) -+ target = gen_reg_rtx (tmode); -+ -+ if (op0mode == SImode && mode0 == HImode) -+ { -+ op0mode = HImode; -+ op0 = gen_lowpart (HImode, op0); -+ } -+ gcc_assert (op0mode == mode0 || op0mode == VOIDmode); -+ -+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) -+ op0 = copy_to_mode_reg (mode0, op0); -+ -+ pat = GEN_FCN (icode) (target, op0); -+ if (! pat) -+ return 0; -+ emit_insn (pat); -+ return target; -+} -+ -+/* Subroutine of avr_expand_builtin to take care of binop insns. */ -+ -+static rtx -+avr_expand_binop_builtin (enum insn_code icode, tree exp, rtx target) -+{ -+ rtx pat; -+ tree arg0 = CALL_EXPR_ARG (exp, 0); -+ tree arg1 = CALL_EXPR_ARG (exp, 1); -+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); -+ rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0); -+ enum machine_mode op0mode = GET_MODE (op0); -+ enum machine_mode op1mode = GET_MODE (op1); -+ enum machine_mode tmode = insn_data[icode].operand[0].mode; -+ enum machine_mode mode0 = insn_data[icode].operand[1].mode; -+ enum machine_mode mode1 = insn_data[icode].operand[2].mode; -+ -+ if (! target -+ || GET_MODE (target) != tmode -+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) -+ target = gen_reg_rtx (tmode); -+ -+ if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode) -+ { -+ op0mode = HImode; -+ op0 = gen_lowpart (HImode, op0); -+ } -+ if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode) -+ { -+ op1mode = HImode; -+ op1 = gen_lowpart (HImode, op1); -+ } -+ /* In case the insn wants input operands in modes different from -+ the result, abort. */ -+ gcc_assert ((op0mode == mode0 || op0mode == VOIDmode) -+ && (op1mode == mode1 || op1mode == VOIDmode)); -+ -+ if (! (*insn_data[icode].operand[1].predicate) (op0, mode0)) -+ op0 = copy_to_mode_reg (mode0, op0); -+ if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)) -+ op1 = copy_to_mode_reg (mode1, op1); -+ -+ pat = GEN_FCN (icode) (target, op0, op1); -+ if (! pat) -+ return 0; -+ -+ emit_insn (pat); -+ return target; -+} -+ -+/* Expand an expression EXP that calls a built-in function, -+ with result going to TARGET if that's convenient -+ (and in mode MODE if that's convenient). -+ SUBTARGET may be used as the target for computing one of EXP's operands. -+ IGNORE is nonzero if the value is to be ignored. */ -+ -+static rtx -+avr_expand_builtin (tree exp, rtx target, -+ rtx subtarget ATTRIBUTE_UNUSED, -+ enum machine_mode mode ATTRIBUTE_UNUSED, -+ int ignore ATTRIBUTE_UNUSED) -+{ -+ size_t i; -+ const struct builtin_description *d; -+ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); -+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl); -+ rtx pat; -+ tree arg0; -+ rtx op0; -+ -+ switch (fcode) -+ { -+ case AVR_BUILTIN_SEI: -+ emit_insn (gen_enable_interrupt ()); -+ return 0; -+ case AVR_BUILTIN_CLI: -+ emit_insn (gen_disable_interrupt ()); -+ return 0; -+ case AVR_BUILTIN_WDR: -+ emit_insn (gen_wdr ()); -+ return 0; -+ case AVR_BUILTIN_SLEEP: -+ emit_insn (gen_sleep ()); -+ return 0; -+ case AVR_BUILTIN_DELAY_CYCLES: -+ { -+ arg0 = CALL_EXPR_ARG (exp, 0); -+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0); -+ -+ if (!CONSTANT_P (op0)) -+ error ("__builtin_avr_delay_cycles expects an integer constant."); -+ -+ emit_insn (gen_delay_cycles (op0)); -+ return 0; -+ } -+ } -+ -+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++) -+ if (d->code == fcode) -+ return avr_expand_unop_builtin (d->icode, exp, target); -+ -+ for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++) -+ if (d->code == fcode) -+ return avr_expand_binop_builtin (d->icode, exp, target); -+ -+ gcc_unreachable (); -+} -+ - #include "gt-avr.h" -diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md -index 96ef48e..45426ce 100644 ---- a/gcc/config/avr/avr.md -+++ b/gcc/config/avr/avr.md -@@ -49,14 +49,29 @@ - - (UNSPEC_STRLEN 0) - (UNSPEC_INDEX_JMP 1) -- (UNSPEC_SEI 2) -- (UNSPEC_CLI 3) -+ (UNSPEC_SWAP 2) -+ (UNSPEC_FMUL 3) -+ (UNSPEC_FMULS 4) -+ (UNSPEC_FMULSU 5) -+ - - (UNSPECV_PROLOGUE_SAVES 0) - (UNSPECV_EPILOGUE_RESTORES 1) - (UNSPECV_WRITE_SP_IRQ_ON 2) - (UNSPECV_WRITE_SP_IRQ_OFF 3) -- (UNSPECV_GOTO_RECEIVER 4)]) -+ (UNSPECV_GOTO_RECEIVER 4) -+ (UNSPECV_SEI 5) -+ (UNSPECV_CLI 6) -+ (UNSPECV_NOP 7) -+ (UNSPECV_NOP2 8) -+ (UNSPECV_SLEEP 9) -+ (UNSPECV_WDR 10) -+ -+ (UNSPECV_DELAY_CYCLES 100) -+ (UNSPECV_DELAY_CYCLES_1 101) -+ (UNSPECV_DELAY_CYCLES_2 102) -+ (UNSPECV_DELAY_CYCLES_3 103) -+ (UNSPECV_DELAY_CYCLES_4 104)]) - - (include "predicates.md") - (include "constraints.md") -@@ -2888,13 +2903,6 @@ - (const_int 1)) - (const_int 3)])]) - --(define_insn "nop" -- [(const_int 0)] -- "" -- "nop" -- [(set_attr "cc" "none") -- (set_attr "length" "1")]) -- - ; indirect jump - (define_insn "indirect_jump" - [(set (pc) (match_operand:HI 0 "register_operand" "!z,*r"))] -@@ -3274,7 +3282,7 @@ - - ;; Enable Interrupts - (define_insn "enable_interrupt" -- [(unspec [(const_int 0)] UNSPEC_SEI)] -+ [(unspec_volatile [(const_int 0)] UNSPECV_SEI)] - "" - "sei" - [(set_attr "length" "1") -@@ -3283,7 +3291,7 @@ - - ;; Disable Interrupts - (define_insn "disable_interrupt" -- [(unspec [(const_int 0)] UNSPEC_CLI)] -+ [(unspec_volatile [(const_int 0)] UNSPECV_CLI)] - "" - "cli" - [(set_attr "length" "1") -@@ -3383,3 +3391,219 @@ - expand_epilogue (); - DONE; - }") -+ -+;;delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay_cycles_delay -+;; delay_cycles -+ -+(define_expand "delay_cycles" -+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i")] -+ UNSPECV_DELAY_CYCLES)] -+ "" -+ " -+ rtx loop_reg; -+ unsigned int cycles = INTVAL (operands[0]); -+ if (IN_RANGE(cycles, 83886082, 0xFFFFFFFF)) -+ { -+ unsigned int loop_count = ((cycles - 9) / 6) + 1; -+ unsigned int cycles_used = (((loop_count - 1) * 6) + 9); -+ emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode))); -+ cycles -= cycles_used; -+ } -+ if (IN_RANGE(cycles, 262145, 83886081)) -+ { -+ unsigned int loop_count = ((cycles - 7) / 5) + 1; -+ if (loop_count > 0xFFFFFF) -+ loop_count = 0xFFFFFF; -+ unsigned int cycles_used = (((loop_count - 1) * 5) + 7); -+ emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode))); -+ cycles -= cycles_used; -+ } -+ if (IN_RANGE(cycles, 768, 262144)) -+ { -+ unsigned int loop_count = ((cycles - 5) / 4) + 1; -+ if (loop_count > 0xFFFF) -+ loop_count = 0xFFFF; -+ unsigned int cycles_used = (((loop_count - 1) * 4) + 5); -+ emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode))); -+ cycles -= cycles_used; -+ } -+ if (IN_RANGE(cycles, 6, 767)) -+ { -+ unsigned int loop_count = (cycles/ 3); -+ if (loop_count > 255) -+ loop_count = 255; -+ unsigned int cycles_used = (loop_count * 3); -+ emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode))); -+ cycles -= cycles_used; -+ } -+ while (cycles >= 2) -+ { -+ emit_insn (gen_nop2 ()); -+ cycles -= 2; -+ } -+ if (cycles == 1) -+ { -+ emit_insn (gen_nop ()); -+ cycles--; -+ } -+ DONE; -+ ") -+ -+(define_insn "delay_cycles_1" -+[(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_1) -+ (match_operand:QI 0 "immediate_operand" "") -+ (clobber (match_scratch:QI 1 "=&d"))] -+ "" -+ " ldi %1,lo8(%0) -+ 1:dec %1 -+ brne 1b" -+ [(set_attr "length" "3") -+ (set_attr "cc" "clobber")]) -+ -+(define_insn "delay_cycles_2" -+ [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_2) -+ (match_operand:HI 0 "immediate_operand" "") -+ (clobber (match_scratch:HI 1 "=&w"))] -+ "" -+ " ldi %A1,lo8(%0) -+ ldi %B1,hi8(%0) -+ 1:sbiw %A1,1 -+ brne 1b" -+ [(set_attr "length" "4") -+ (set_attr "cc" "clobber")]) -+ -+(define_insn "delay_cycles_3" -+ [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_3) -+ (match_operand:SI 0 "immediate_operand" "") -+ (clobber (match_scratch:SI 1 "=&d"))] -+ "" -+ " ldi %A1,lo8(%0) -+ ldi %B1,hi8(%0) -+ ldi %C1,hlo8(%0) -+ 1:subi %A1,1 -+ sbci %B1,0 -+ sbci %C1,0 -+ brne 1b" -+ [(set_attr "length" "7") -+ (set_attr "cc" "clobber")]) -+ -+(define_insn "delay_cycles_4" -+ [(unspec_volatile [(const_int 0)] UNSPECV_DELAY_CYCLES_4) -+ (match_operand:SI 0 "immediate_operand" "") -+ (clobber (match_scratch:SI 1 "=&d"))] -+ "" -+ " ldi %A1,lo8(%0) -+ ldi %B1,hi8(%0) -+ ldi %C1,hlo8(%0) -+ ldi %D1,hhi8(%0) -+ 1:subi %A1,1 -+ sbci %B1,0 -+ sbci %C1,0 -+ sbci %D1,0 -+ brne 1b" -+ [(set_attr "length" "9") -+ (set_attr "cc" "clobber")]) -+ -+;; CPU instructions -+ -+;; NOP -+(define_insn "nop" -+ [(unspec_volatile [(const_int 0)] UNSPECV_NOP)] -+ "" -+ "nop" -+ [(set_attr "length" "1") -+ (set_attr "cc" "none")]) -+ -+;; NOP2 -+(define_insn "nop2" -+ [(unspec_volatile [(const_int 0)] UNSPECV_NOP2)] -+ "" -+ "rjmp ." -+ [(set_attr "length" "1") -+ (set_attr "cc" "none")]) -+ -+;; SEI, Enable Interrupts -+;(define_insn "sei" -+; [(unspec_volatile [(const_int 0)] UNSPECV_SEI)] -+; "" -+; "sei" -+; [(set_attr "length" "1") -+; (set_attr "cc" "none") -+; ]) -+ -+;; CLI, Disable Interrupts -+;(define_insn "cli" -+; [(unspec_volatile [(const_int 0)] UNSPECV_CLI)] -+; "" -+; "cli" -+; [(set_attr "length" "1") -+; (set_attr "cc" "none") -+; ]) -+ -+;; SLEEP -+(define_insn "sleep" -+ [(unspec_volatile [(const_int 0)] UNSPECV_SLEEP)] -+ "" -+ "sleep" -+ [(set_attr "length" "1") -+ (set_attr "cc" "none") -+ ]) -+ -+;; WDR -+(define_insn "wdr" -+ [(unspec_volatile [(const_int 0)] UNSPECV_WDR)] -+ "" -+ "wdr" -+ [(set_attr "length" "1") -+ (set_attr "cc" "none") -+ ]) -+ -+;; SWAP -+(define_insn "swap" -+ [(set (match_operand:QI 0 "register_operand" "=r") -+ (unspec:QI [(match_operand:QI 1 "register_operand" "0")] -+ UNSPEC_SWAP))] -+ "" -+ "swap %0" -+ [(set_attr "length" "1") -+ (set_attr "cc" "none")]) -+ -+;; FMUL -+(define_insn "fmul" -+ [(set (match_operand:HI 0 "a_register_operand" "=r") -+ (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") -+ (match_operand:QI 2 "a_register_operand" "r")] -+ UNSPEC_FMUL))] -+ "AVR_HAVE_MUL" -+ "fmul %1,%2 -+ movw %0,r0 -+ clr r1" -+ [(set_attr "length" "3") -+ (set_attr "cc" "clobber")]) -+ -+;; FMULS -+(define_insn "fmuls" -+ [(set (match_operand:HI 0 "a_register_operand" "=r") -+ (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") -+ (match_operand:QI 2 "a_register_operand" "r")] -+ UNSPEC_FMULS))] -+ "AVR_HAVE_MUL" -+ "fmuls %1,%2 -+ movw %0,r0 -+ clr r1" -+ [(set_attr "length" "3") -+ (set_attr "cc" "clobber")]) -+ -+;; FMULSU -+(define_insn "fmulsu" -+ [(set (match_operand:HI 0 "a_register_operand" "=r") -+ (unspec:HI [(match_operand:QI 1 "a_register_operand" "r") -+ (match_operand:QI 2 "a_register_operand" "r")] -+ UNSPEC_FMULSU))] -+ "AVR_HAVE_MUL" -+ "fmulsu %1,%2 -+ movw %0,r0 -+ clr r1" -+ [(set_attr "length" "3") -+ (set_attr "cc" "clobber")]) -+ -diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md -index 3ff85fd..f3f181c 100755 ---- a/gcc/config/avr/predicates.md -+++ b/gcc/config/avr/predicates.md -@@ -27,6 +27,11 @@ - (and (match_code "reg") - (match_test "REGNO (op) >= 16 && REGNO (op) <= 31"))) - -+;; Registers from r16 to 24. -+(define_predicate "a_register_operand" -+ (and (match_code "reg") -+ (match_test "REGNO (op) >= 16 && REGNO (op) <= 24"))) -+ - (define_predicate "even_register_operand" - (and (match_code "reg") - (and (match_test "REGNO (op) <= 31") --- -1.6.0.4 - |