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

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).