public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch][AVR]: Initial builtins support
@ 2011-04-06 14:11 Georg-Johann Lay
  2011-04-06 15:16 ` Georg-Johann Lay
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Georg-Johann Lay @ 2011-04-06 14:11 UTC (permalink / raw)
  To: gcc-patches; +Cc: Denis Chertykov, Eric Weddington, Anatoly Sokolov

[-- Attachment #1: Type: text/plain, Size: 1780 bytes --]

This patch adds builtin support for some RTL builtins to avr backend.
One builtin implements loop for delay of specific number of ticks
(under the assumption IRQs are off), others simply map to machine
instructions like SEI, CLI, NOP, SLEEP, WDR, FMUL, FMAULS, FMULSU.

In addition, builtin macros are introduced so that use can easily
query if or if not a specific builtin is available. This might be
useful as builtin support evolves, because #ifdef is easier then to
twiddle out which version brings what builtin.

2011-04-06  Georg-Johann Lay  <avr@gjlay.de>

	* config/avr/avr.c: ("insn-codes.h", "optabs.h", "langhooks.h"):
	New Includes
	(avr_init_builtins, avr_expand_builtin,
	avr_expand_delay_cycles, avr_expand_unop_builtin,
	avr_expand_binop_builtin ): New functions.
	(avr_builtin_id): New enum
	(struct avr_builtin_description): New struct
	(bdesc_1arg, bdesc_2arg): New arrays describing some RTL builtins.
	(TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define.
	* config/avr/avr.md (UNSPEC_FMUL, UNSPEC_FMULS, UNSPEC_FMULSU,
	UNSPECV_ENABLE_IRQS, UNSPECV_NOP, UNSPECV_SLEEP, UNSPECV_WDR,
	UNSPECV_DELAY_CYCLES): new enumeration values
	(UNSPEC_SEI, UNSPEC_CLI): Remove enumeration values
	("enable_interrupt"): Use UNSPECV_ENABLE_IRQS
	("disable_interrupt"): Use UNSPECV_ENABLE_IRQS
	("*rotlqi3_4"): rename insn to "rotlqi3_4"
	("delay_cycles_1", "delay_cycles_2", "delay_cycles_3",
	"delay_cycles_4", "nopv", "sleep", "wdr", "fmul", "fmuls",
	"fmulsu"): New insns
	* config/avr/avr-c.c: fix line endings
	(avr_cpu_cpp_builtins): New builtin defines: __BUILTIN_AVR_NOP,
	__BUILTIN_AVR_SEI, __BUILTIN_AVR_CLI, __BUILTIN_AVR_WDR,
	__BUILTIN_AVR_SLEEP, __BUILTIN_AVR_SWAP,
	__BUILTIN_AVR_DELAY_CYCLES, __BUILTIN_AVR_FMUL,
	__BUILTIN_AVR_FMULS, __BUILTIN_AVR_FMULSU.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: builtin-v2.diff --]
[-- Type: text/x-patch; name="builtin-v2.diff", Size: 23323 bytes --]

Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(Revision 172036)
+++ config/avr/avr.c	(Arbeitskopie)
@@ -29,6 +29,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"
@@ -38,7 +39,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"
@@ -91,6 +94,8 @@ static bool avr_rtx_costs (rtx, int, int
 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);
 static unsigned int avr_case_values_threshold (void);
@@ -253,6 +258,13 @@ static const struct default_options avr_
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
 
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS avr_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN avr_expand_builtin
+
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 static void
@@ -6426,4 +6438,331 @@ unsigned int avr_case_values_threshold (
   return (!AVR_HAVE_JMP_CALL || TARGET_CALL_PROLOGUES) ? 8 : 17;
 }
 
+/* Helper for __builtin_avr_delay_cycles */
+
+static void
+avr_expand_delay_cycles (rtx operands0)
+{
+  unsigned HOST_WIDE_INT cycles = UINTVAL (operands0);
+  unsigned HOST_WIDE_INT cycles_used;
+  unsigned HOST_WIDE_INT loop_count;
+  
+  if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
+    {
+      loop_count = ((cycles - 9) / 6) + 1;
+      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))
+    {
+      loop_count = ((cycles - 7) / 5) + 1;
+      if (loop_count > 0xFFFFFF)
+        loop_count = 0xFFFFFF;
+      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))
+    {
+      loop_count = ((cycles - 5) / 4) + 1;
+      if (loop_count > 0xFFFF)
+        loop_count = 0xFFFF;
+      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))
+    {
+      loop_count = cycles / 3;
+      if (loop_count > 255) 
+        loop_count = 255;
+      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_nopv (GEN_INT(2)));
+      cycles -= 2;
+    }
+
+  if (cycles == 1)
+    {
+      emit_insn (gen_nopv (GEN_INT(1)));
+      cycles--;
+    }
+}
+
+/* IDs for all the AVR builtins.  */
+
+enum avr_builtin_id
+  {
+    AVR_BUILTIN_NOP,
+    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)
+
+
+/* Implement `TARGET_INIT_BUILTINS' */
+/* 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_nop", void_ftype_void, AVR_BUILTIN_NOP);
+  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);
+  DEF_BUILTIN ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP);
+  DEF_BUILTIN ("__builtin_avr_delay_cycles", void_ftype_ulong, 
+               AVR_BUILTIN_DELAY_CYCLES);
+
+  if (AVR_HAVE_MUL)
+    {
+      /* FIXME: If !AVR_HAVE_MUL, make respective functions available
+         in libgcc. For fmul and fmuls this is straight forward with
+         upcoming fixed point support. */
+      
+      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);
+    }
+}
+
+#undef DEF_BUILTIN
+
+struct avr_builtin_description
+{
+  const enum insn_code icode;
+  const char *const name;
+  const enum avr_builtin_id id;
+};
+
+static const struct avr_builtin_description
+bdesc_1arg[] =
+  {
+    { CODE_FOR_rotlqi3_4, "__builtin_avr_swap", AVR_BUILTIN_SWAP }
+  };
+
+static const struct avr_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 avr_builtin_description *d;
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  unsigned int id = DECL_FUNCTION_CODE (fndecl);
+  tree arg0;
+  rtx op0;
+
+  switch (id)
+    {
+    case AVR_BUILTIN_NOP:
+      emit_insn (gen_nopv (GEN_INT(1)));
+      return 0;
+      
+    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 (! CONST_INT_P (op0))
+          error ("__builtin_avr_delay_cycles expects a compile time integer constant.");
+
+        avr_expand_delay_cycles (op0);
+        return 0;
+      }
+    }
+
+  for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
+    if (d->id == id)
+      return avr_expand_unop_builtin (d->icode, exp, target);
+
+  for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
+    if (d->id == id)
+      return avr_expand_binop_builtin (d->icode, exp, target);
+
+  gcc_unreachable ();
+}
+
+
 #include "gt-avr.h"
Index: config/avr/avr.md
===================================================================
--- config/avr/avr.md	(Revision 172036)
+++ config/avr/avr.md	(Arbeitskopie)
@@ -35,9 +35,6 @@
 ;;  ~  Output 'r' if not AVR_HAVE_JMP_CALL.
 ;;  !  Output 'e' if AVR_HAVE_EIJMP_EICALL.
 
-;; UNSPEC usage:
-;;  0  Length of a string, see "strlenhi".
-;;  1  Jump by register pair Z or by table addressed by Z, see "casesi".
 
 (define_constants
   [(REG_X	26)
@@ -50,17 +47,29 @@ (define_constants
    
    (SREG_ADDR   0x5F)
    (RAMPZ_ADDR  0x5B)
-   
-   (UNSPEC_STRLEN	0)
-   (UNSPEC_INDEX_JMP	1)
-   (UNSPEC_SEI		2)
-   (UNSPEC_CLI		3)
-
-   (UNSPECV_PROLOGUE_SAVES	0)
-   (UNSPECV_EPILOGUE_RESTORES	1)
-   (UNSPECV_WRITE_SP_IRQ_ON	2)
-   (UNSPECV_WRITE_SP_IRQ_OFF	3)
-   (UNSPECV_GOTO_RECEIVER	4)])
+   ])
+
+(define_c_enum "unspec"
+  [UNSPEC_STRLEN
+   UNSPEC_INDEX_JMP
+   UNSPEC_FMUL
+   UNSPEC_FMULS
+   UNSPEC_FMULSU
+   ])
+
+(define_c_enum "unspecv"
+  [UNSPECV_PROLOGUE_SAVES
+   UNSPECV_EPILOGUE_RESTORES
+   UNSPECV_WRITE_SP_IRQ_ON
+   UNSPECV_WRITE_SP_IRQ_OFF
+   UNSPECV_GOTO_RECEIVER
+   UNSPECV_ENABLE_IRQS
+   UNSPECV_NOP
+   UNSPECV_SLEEP
+   UNSPECV_WDR
+   UNSPECV_DELAY_CYCLES
+   ])
+    
 
 (include "predicates.md")
 (include "constraints.md")
@@ -1489,7 +1498,7 @@ (define_expand "rotlqi3"
     FAIL;
 }")
 
-(define_insn "*rotlqi3_4"
+(define_insn "rotlqi3_4"
   [(set (match_operand:QI 0 "register_operand" "=r")
 	(rotate:QI (match_operand:QI 1 "register_operand" "0")
 		   (const_int 4)))]
@@ -3130,21 +3139,19 @@ (define_insn "popqi"
 
 ;; Enable Interrupts
 (define_insn "enable_interrupt"
-  [(unspec [(const_int 0)] UNSPEC_SEI)]
+  [(unspec_volatile [(const_int 1)] UNSPECV_ENABLE_IRQS)]
   ""
   "sei"
   [(set_attr "length" "1")
-  (set_attr "cc" "none")
-  ])
+   (set_attr "cc" "none")])
 
 ;; Disable Interrupts
 (define_insn "disable_interrupt"
-  [(unspec [(const_int 0)] UNSPEC_CLI)]
+  [(unspec_volatile [(const_int 0)] UNSPECV_ENABLE_IRQS)]
   ""
   "cli"
   [(set_attr "length" "1")
-  (set_attr "cc" "none")
-  ])
+   (set_attr "cc" "none")])
 
 ;;  Library prologue saves
 (define_insn "call_prologue_saves"
@@ -3246,3 +3253,138 @@ (define_expand "sibcall_epilogue"
     expand_epilogue (true /* sibcall_p */);
     DONE;
   })
+
+;; Some instructions resp. instruction sequences available
+;; via builtins.
+
+(define_insn "delay_cycles_1"
+  [(unspec_volatile [(match_operand:QI 0 "const_int_operand" "n")
+                     (const_int 1)]
+                    UNSPECV_DELAY_CYCLES)
+   (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 [(match_operand:HI 0 "const_int_operand" "n")
+                     (const_int 2)]
+                    UNSPECV_DELAY_CYCLES)
+   (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 [(match_operand:SI 0 "const_int_operand" "n")
+                     (const_int 3)]
+                    UNSPECV_DELAY_CYCLES)
+   (clobber (match_scratch:QI 1 "=&d"))
+   (clobber (match_scratch:QI 2 "=&d"))
+   (clobber (match_scratch:QI 3 "=&d"))]
+  ""
+  "ldi %1,lo8(%0)
+	ldi %2,hi8(%0)
+	ldi %3,hlo8(%0)
+	1: subi %1,1
+	sbci %2,0
+	sbci %3,0
+	brne 1b"
+  [(set_attr "length" "7")
+   (set_attr "cc" "clobber")])
+
+(define_insn "delay_cycles_4"
+  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "n")
+                     (const_int 4)]
+                    UNSPECV_DELAY_CYCLES)
+   (clobber (match_scratch:QI 1 "=&d"))
+   (clobber (match_scratch:QI 2 "=&d"))
+   (clobber (match_scratch:QI 3 "=&d"))
+   (clobber (match_scratch:QI 4 "=&d"))]
+  ""
+  "ldi %1,lo8(%0)
+	ldi %2,hi8(%0)
+	ldi %3,hlo8(%0)
+	ldi %4,hhi8(%0)
+	1: subi %1,1
+	sbci %2,0
+	sbci %3,0
+	sbci %4,0
+	brne 1b"
+  [(set_attr "length" "9")
+   (set_attr "cc" "clobber")])
+
+;; CPU instructions
+
+;; NOP taking 1 or 2 Ticks 
+(define_insn "nopv"
+  [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "P,K")] 
+                    UNSPECV_NOP)]
+  ""
+  "@
+	nop
+	rjmp ."
+  [(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")])
+  
+;; FMUL
+(define_insn "fmul"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "register_operand" "a")
+		    (match_operand:QI 2 "register_operand" "a")]
+                   UNSPEC_FMUL))]
+  "AVR_HAVE_MUL"
+  "fmul %1,%2
+	movw %0,r0
+	clr __zero_reg__"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+;; FMULS
+(define_insn "fmuls"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "register_operand" "a")
+		    (match_operand:QI 2 "register_operand" "a")]
+		    UNSPEC_FMULS))]
+  "AVR_HAVE_MUL"
+  "fmuls %1,%2
+	movw %0,r0
+	clr __zero_reg__"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
+
+;; FMULSU
+(define_insn "fmulsu"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+	(unspec:HI [(match_operand:QI 1 "register_operand" "a")
+		    (match_operand:QI 2 "register_operand" "a")]
+                   UNSPEC_FMULSU))]
+  "AVR_HAVE_MUL"
+  "fmulsu %1,%2
+	movw %0,r0
+	clr __zero_reg__"
+  [(set_attr "length" "3")
+   (set_attr "cc" "clobber")])
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(Revision 172036)
+++ config/avr/avr-c.c	(Arbeitskopie)
@@ -1,85 +1,104 @@
-/* Copyright (C) 2009, 2010
-   Free Software Foundation, Inc.
-   Contributed by Anatoly Sokolov (aesok@post.ru)
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3, or (at your option)
-   any later version.
-   
-   GCC is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING3.  If not see
-   <http://www.gnu.org/licenses/>.  */
-
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tm_p.h"
-#include "cpplib.h"
-#include "tree.h"
-#include "c-family/c-common.h"
-
-/* Not included in avr.c since this requires C front end.  */
-
-/* Worker function for TARGET_CPU_CPP_BUILTINS.  */
-
-void
-avr_cpu_cpp_builtins (struct cpp_reader *pfile)
-{
-  builtin_define_std ("AVR");
-
-  if (avr_current_arch->macro)
-    cpp_define (pfile, avr_current_arch->macro);
-  if (avr_extra_arch_macro)
-    cpp_define (pfile, avr_extra_arch_macro);
-  if (avr_current_arch->have_elpm)
-    cpp_define (pfile, "__AVR_HAVE_RAMPZ__");
-  if (avr_current_arch->have_elpm)
-    cpp_define (pfile, "__AVR_HAVE_ELPM__");
-  if (avr_current_arch->have_elpmx)
-    cpp_define (pfile, "__AVR_HAVE_ELPMX__");
-  if (avr_current_arch->have_movw_lpmx)
-    {
-      cpp_define (pfile, "__AVR_HAVE_MOVW__");
-      cpp_define (pfile, "__AVR_HAVE_LPMX__");
-    }
-  if (avr_current_arch->asm_only)
-    cpp_define (pfile, "__AVR_ASM_ONLY__");
-  if (avr_current_arch->have_mul)
-    {
-      cpp_define (pfile, "__AVR_ENHANCED__");
-      cpp_define (pfile, "__AVR_HAVE_MUL__");
-    }
-  if (avr_current_arch->have_jmp_call)
-    {
-      cpp_define (pfile, "__AVR_MEGA__");
-      cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
-    }
-  if (avr_current_arch->have_eijmp_eicall)
-    {
-      cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
-      cpp_define (pfile, "__AVR_3_BYTE_PC__");
-    }
-  else
-    {
-      cpp_define (pfile, "__AVR_2_BYTE_PC__");
-    }
-
-  if (avr_current_device->short_sp)
-    cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
-  else
-    cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
-
-  if (TARGET_NO_INTERRUPTS)
-    cpp_define (pfile, "__NO_INTERRUPTS__");
-}
-
+/* Copyright (C) 2009, 2010
+   Free Software Foundation, Inc.
+   Contributed by Anatoly Sokolov (aesok@post.ru)
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+   
+   GCC is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tm_p.h"
+#include "cpplib.h"
+#include "tree.h"
+#include "c-family/c-common.h"
+
+/* Not included in avr.c since this requires C front end.  */
+
+/* Worker function for TARGET_CPU_CPP_BUILTINS.  */
+
+void
+avr_cpu_cpp_builtins (struct cpp_reader *pfile)
+{
+  builtin_define_std ("AVR");
+
+  if (avr_current_arch->macro)
+    cpp_define (pfile, avr_current_arch->macro);
+  if (avr_extra_arch_macro)
+    cpp_define (pfile, avr_extra_arch_macro);
+  if (avr_current_arch->have_elpm)
+    cpp_define (pfile, "__AVR_HAVE_RAMPZ__");
+  if (avr_current_arch->have_elpm)
+    cpp_define (pfile, "__AVR_HAVE_ELPM__");
+  if (avr_current_arch->have_elpmx)
+    cpp_define (pfile, "__AVR_HAVE_ELPMX__");
+  if (avr_current_arch->have_movw_lpmx)
+    {
+      cpp_define (pfile, "__AVR_HAVE_MOVW__");
+      cpp_define (pfile, "__AVR_HAVE_LPMX__");
+    }
+  if (avr_current_arch->asm_only)
+    cpp_define (pfile, "__AVR_ASM_ONLY__");
+  if (avr_current_arch->have_mul)
+    {
+      cpp_define (pfile, "__AVR_ENHANCED__");
+      cpp_define (pfile, "__AVR_HAVE_MUL__");
+    }
+  if (avr_current_arch->have_jmp_call)
+    {
+      cpp_define (pfile, "__AVR_MEGA__");
+      cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
+    }
+  if (avr_current_arch->have_eijmp_eicall)
+    {
+      cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
+      cpp_define (pfile, "__AVR_3_BYTE_PC__");
+    }
+  else
+    {
+      cpp_define (pfile, "__AVR_2_BYTE_PC__");
+    }
+
+  if (avr_current_device->short_sp)
+    cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
+  else
+    cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
+
+  if (TARGET_NO_INTERRUPTS)
+    cpp_define (pfile, "__NO_INTERRUPTS__");
+
+  /* Define builtin macros so that the user can
+     easily query if or if not a specific builtin
+     is available. */
+
+  cpp_define (pfile, "__BUILTIN_AVR_NOP");
+  cpp_define (pfile, "__BUILTIN_AVR_SEI");
+  cpp_define (pfile, "__BUILTIN_AVR_CLI");
+  cpp_define (pfile, "__BUILTIN_AVR_WDR");
+  cpp_define (pfile, "__BUILTIN_AVR_SLEEP");
+  cpp_define (pfile, "__BUILTIN_AVR_SWAP");
+  cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES");
+
+  if (AVR_HAVE_MUL)
+    {
+      cpp_define (pfile, "__BUILTIN_AVR_FMUL");
+      cpp_define (pfile, "__BUILTIN_AVR_FMULS");
+      cpp_define (pfile, "__BUILTIN_AVR_FMULSU");
+    }
+}
+

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch][AVR]: Initial builtins support
  2011-04-06 14:11 [Patch][AVR]: Initial builtins support Georg-Johann Lay
@ 2011-04-06 15:16 ` Georg-Johann Lay
  2011-04-06 18:55 ` Georg-Johann Lay
  2011-04-11 11:18 ` Georg-Johann Lay
  2 siblings, 0 replies; 5+ messages in thread
From: Georg-Johann Lay @ 2011-04-06 15:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: Denis Chertykov, Eric Weddington, Anatoly Sokolov

[-- Attachment #1: Type: text/plain, Size: 199 bytes --]

Patch for user documentation.

2011-04-06  Georg-Johann Lay  <avr@gjlay.de>

	* doc/extend.texi (Target Builtins): Add documentation of AVR
	built-in functions.
	(AVR Built-in Functions): New node
	

[-- Attachment #2: builtin-doc.diff --]
[-- Type: text/x-patch, Size: 2156 bytes --]

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(Revision 172046)
+++ doc/extend.texi	(Arbeitskopie)
@@ -7924,6 +7924,7 @@ instructions, but allow the compiler to
 * Alpha Built-in Functions::
 * ARM iWMMXt Built-in Functions::
 * ARM NEON Intrinsics::
+* AVR Built-in Functions::
 * Blackfin Built-in Functions::
 * FR-V Built-in Functions::
 * X86 Built-in Functions::
@@ -8175,6 +8176,44 @@ when the @option{-mfpu=neon} switch is u
 
 @include arm-neon-intrinsics.texi
 
+@node AVR Built-in Functions
+@subsection AVR Built-in Functions
+
+For each built-in function for AVR, there is an equally named,
+uppercase built-in macro defined. That way users can easily query if
+or if not a specific built-in is implemented or not. For example, if
+@code{__builtin_avr_nop} is available the macro
+@code{__BUILTIN_AVR_NOP} is defined to @code{1} and undefined otherwise.
+
+The following built-in functions map to the respective machine
+instruction, i.e. @code{nop}, @code{sei}, @code{cli}, @code{sleep},
+@code{wdr}, @code{swap}, @code{fmul}, @code{fmuls}
+resp. @code{fmulsu}. The latter three are only available if the AVR
+device actually supports multiplication.
+
+@smallexample
+void __builtin_avr_nop (void)
+void __builtin_avr_sei (void)
+void __builtin_avr_cli (void)
+void __builtin_avr_sleep (void)
+void __builtin_avr_wdr (void)
+unsigned char __builtin_avr_swap (unsigned char)
+unsigned int __builtin_avr_fmul (unsigned char, unsigned char)
+int __builtin_avr_fmuls (char, char)
+int __builtin_avr_fmulsu (char, unsigned char)
+@end smallexample
+
+In order to delay execution for a specific number of cycles, GCC
+implements
+@smallexample
+void __builtin_avr_delay_cycles (unsigned long ticks)
+@end smallexample
+
+@code{ticks} is the number of ticks to delay execution. Note that this
+built-in does not take into account the effect of interrupts which
+might increase delay time. @code{ticks} must be a compile time
+integer constant; delays with a variable number of cycles are not supported.
+
 @node Blackfin Built-in Functions
 @subsection Blackfin Built-in Functions
 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch][AVR]: Initial builtins support
  2011-04-06 14:11 [Patch][AVR]: Initial builtins support Georg-Johann Lay
  2011-04-06 15:16 ` Georg-Johann Lay
@ 2011-04-06 18:55 ` Georg-Johann Lay
  2011-04-11 11:18 ` Georg-Johann Lay
  2 siblings, 0 replies; 5+ messages in thread
From: Georg-Johann Lay @ 2011-04-06 18:55 UTC (permalink / raw)
  To: gcc-patches; +Cc: Denis Chertykov, Eric Weddington, Anatoly Sokolov

Added Anatoly and Eric to changelog entry

Johann


2011-04-06  Anatoly Sokolov <aesok@post.ru>
             Eric Weddington <eric.weddington@atmel.com>
             Georg-Johann Lay  <avr@gjlay.de>

	* config/avr/avr.c: ("insn-codes.h", "optabs.h", "langhooks.h"):
	New Includes
	(avr_init_builtins, avr_expand_builtin,
	avr_expand_delay_cycles, avr_expand_unop_builtin,
	avr_expand_binop_builtin ): New static functions.
	(avr_builtin_id): New enum
	(struct avr_builtin_description): New struct
	(bdesc_1arg, bdesc_2arg): New arrays describing some RTL builtins.
	(TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define.
	* config/avr/avr.md (UNSPEC_FMUL, UNSPEC_FMULS, UNSPEC_FMULSU,
	UNSPECV_ENABLE_IRQS, UNSPECV_NOP, UNSPECV_SLEEP, UNSPECV_WDR,
	UNSPECV_DELAY_CYCLES): new enumeration values
	(UNSPEC_SEI, UNSPEC_CLI): Remove enumeration values
	("enable_interrupt"): Use UNSPECV_ENABLE_IRQS
	("disable_interrupt"): Use UNSPECV_ENABLE_IRQS
	("*rotlqi3_4"): rename to named insn "rotlqi3_4"
	("delay_cycles_1", "delay_cycles_2", "delay_cycles_3",
	"delay_cycles_4", "nopv", "sleep", "wdr", "fmul", "fmuls",
	"fmulsu"): New insns
	* config/avr/avr-c.c: fix line endings
	(avr_cpu_cpp_builtins): New builtin defines: __BUILTIN_AVR_NOP,
	__BUILTIN_AVR_SEI, __BUILTIN_AVR_CLI, __BUILTIN_AVR_WDR,
	__BUILTIN_AVR_SLEEP, __BUILTIN_AVR_SWAP,
	__BUILTIN_AVR_DELAY_CYCLES, __BUILTIN_AVR_FMUL,
	__BUILTIN_AVR_FMULS, __BUILTIN_AVR_FMULSU.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re:Ping: [Patch][AVR]: Initial builtins support
  2011-04-06 14:11 [Patch][AVR]: Initial builtins support Georg-Johann Lay
  2011-04-06 15:16 ` Georg-Johann Lay
  2011-04-06 18:55 ` Georg-Johann Lay
@ 2011-04-11 11:18 ` Georg-Johann Lay
  2011-04-12  5:38   ` Ping: " Denis Chertykov
  2 siblings, 1 reply; 5+ messages in thread
From: Georg-Johann Lay @ 2011-04-11 11:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: Denis Chertykov, Eric Weddington, Anatoly Sokolov

Georg-Johann Lay schrieb:
> This patch adds builtin support for some RTL builtins to avr backend.
> One builtin implements loop for delay of specific number of ticks
> (under the assumption IRQs are off), others simply map to machine
> instructions like SEI, CLI, NOP, SLEEP, WDR, FMUL, FMAULS, FMULSU.
> 
> In addition, builtin macros are introduced so that use can easily
> query if or if not a specific builtin is available. This might be
> useful as builtin support evolves, because #ifdef is easier then to
> twiddle out which version brings what builtin.
> 
> 2011-04-06  Georg-Johann Lay  <avr@gjlay.de>
> 
> 	* config/avr/avr.c: ("insn-codes.h", "optabs.h", "langhooks.h"):
> 	New Includes
> 	(avr_init_builtins, avr_expand_builtin,
> 	avr_expand_delay_cycles, avr_expand_unop_builtin,
> 	avr_expand_binop_builtin ): New functions.
> 	(avr_builtin_id): New enum
> 	(struct avr_builtin_description): New struct
> 	(bdesc_1arg, bdesc_2arg): New arrays describing some RTL builtins.
> 	(TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define.
> 	* config/avr/avr.md (UNSPEC_FMUL, UNSPEC_FMULS, UNSPEC_FMULSU,
> 	UNSPECV_ENABLE_IRQS, UNSPECV_NOP, UNSPECV_SLEEP, UNSPECV_WDR,
> 	UNSPECV_DELAY_CYCLES): new enumeration values
> 	(UNSPEC_SEI, UNSPEC_CLI): Remove enumeration values
> 	("enable_interrupt"): Use UNSPECV_ENABLE_IRQS
> 	("disable_interrupt"): Use UNSPECV_ENABLE_IRQS
> 	("*rotlqi3_4"): rename insn to "rotlqi3_4"
> 	("delay_cycles_1", "delay_cycles_2", "delay_cycles_3",
> 	"delay_cycles_4", "nopv", "sleep", "wdr", "fmul", "fmuls",
> 	"fmulsu"): New insns
> 	* config/avr/avr-c.c: fix line endings
> 	(avr_cpu_cpp_builtins): New builtin defines: __BUILTIN_AVR_NOP,
> 	__BUILTIN_AVR_SEI, __BUILTIN_AVR_CLI, __BUILTIN_AVR_WDR,
> 	__BUILTIN_AVR_SLEEP, __BUILTIN_AVR_SWAP,
> 	__BUILTIN_AVR_DELAY_CYCLES, __BUILTIN_AVR_FMUL,
> 	__BUILTIN_AVR_FMULS, __BUILTIN_AVR_FMULSU.
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Ping: [Patch][AVR]: Initial builtins support
  2011-04-11 11:18 ` Georg-Johann Lay
@ 2011-04-12  5:38   ` Denis Chertykov
  0 siblings, 0 replies; 5+ messages in thread
From: Denis Chertykov @ 2011-04-12  5:38 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc-patches, Eric Weddington, Anatoly Sokolov

2011/4/11 Georg-Johann Lay <avr@gjlay.de>:
> Georg-Johann Lay schrieb:
>> This patch adds builtin support for some RTL builtins to avr backend.
>> One builtin implements loop for delay of specific number of ticks
>> (under the assumption IRQs are off), others simply map to machine
>> instructions like SEI, CLI, NOP, SLEEP, WDR, FMUL, FMAULS, FMULSU.
>>
>> In addition, builtin macros are introduced so that use can easily
>> query if or if not a specific builtin is available. This might be
>> useful as builtin support evolves, because #ifdef is easier then to
>> twiddle out which version brings what builtin.
>>
>> 2011-04-06  Georg-Johann Lay  <avr@gjlay.de>
>>
>>       * config/avr/avr.c: ("insn-codes.h", "optabs.h", "langhooks.h"):
>>       New Includes
>>       (avr_init_builtins, avr_expand_builtin,
>>       avr_expand_delay_cycles, avr_expand_unop_builtin,
>>       avr_expand_binop_builtin ): New functions.
>>       (avr_builtin_id): New enum
>>       (struct avr_builtin_description): New struct
>>       (bdesc_1arg, bdesc_2arg): New arrays describing some RTL builtins.
>>       (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): Define.
>>       * config/avr/avr.md (UNSPEC_FMUL, UNSPEC_FMULS, UNSPEC_FMULSU,
>>       UNSPECV_ENABLE_IRQS, UNSPECV_NOP, UNSPECV_SLEEP, UNSPECV_WDR,
>>       UNSPECV_DELAY_CYCLES): new enumeration values
>>       (UNSPEC_SEI, UNSPEC_CLI): Remove enumeration values
>>       ("enable_interrupt"): Use UNSPECV_ENABLE_IRQS
>>       ("disable_interrupt"): Use UNSPECV_ENABLE_IRQS
>>       ("*rotlqi3_4"): rename insn to "rotlqi3_4"
>>       ("delay_cycles_1", "delay_cycles_2", "delay_cycles_3",
>>       "delay_cycles_4", "nopv", "sleep", "wdr", "fmul", "fmuls",
>>       "fmulsu"): New insns
>>       * config/avr/avr-c.c: fix line endings
>>       (avr_cpu_cpp_builtins): New builtin defines: __BUILTIN_AVR_NOP,
>>       __BUILTIN_AVR_SEI, __BUILTIN_AVR_CLI, __BUILTIN_AVR_WDR,
>>       __BUILTIN_AVR_SLEEP, __BUILTIN_AVR_SWAP,
>>       __BUILTIN_AVR_DELAY_CYCLES, __BUILTIN_AVR_FMUL,
>>       __BUILTIN_AVR_FMULS, __BUILTIN_AVR_FMULSU.
>>

Approved.

Denis.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2011-04-12  5:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-06 14:11 [Patch][AVR]: Initial builtins support Georg-Johann Lay
2011-04-06 15:16 ` Georg-Johann Lay
2011-04-06 18:55 ` Georg-Johann Lay
2011-04-11 11:18 ` Georg-Johann Lay
2011-04-12  5:38   ` Ping: " Denis Chertykov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).