Commit 43ea6502 by Anatoly Sokolov Committed by Georg-Johann Lay

avr.c: ("insn-codes.h"...


	* 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.
	
	* doc/extend.texi (AVR Built-in Functions): New node
	(Target Builtins): Add documentation of AVR
	built-in functions.


Co-Authored-By: Eric Weddington <eric.weddington@atmel.com>
Co-Authored-By: Georg-Johann Lay <avr@gjlay.de>

From-SVN: r172416
parent 8a9b55f3
2011-04-14 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 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.
* doc/extend.texi (AVR Built-in Functions): New node
(Target Builtins): Add documentation of AVR
built-in functions.
2011-04-14 Georg-Johann Lay <avr@gjlay.de> 2011-04-14 Georg-Johann Lay <avr@gjlay.de>
PR target/44643 PR target/44643
......
/* Copyright (C) 2009, 2010 /* Copyright (C) 2009, 2010
Free Software Foundation, Inc. Free Software Foundation, Inc.
Contributed by Anatoly Sokolov (aesok@post.ru) Contributed by Anatoly Sokolov (aesok@post.ru)
This file is part of GCC. This file is part of GCC.
GCC is free software; you can redistribute it and/or modify GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option) the Free Software Foundation; either version 3, or (at your option)
any later version. any later version.
GCC is distributed in the hope that it will be useful, GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */ <http://www.gnu.org/licenses/>. */
#include "config.h" #include "config.h"
#include "system.h" #include "system.h"
#include "coretypes.h" #include "coretypes.h"
#include "tm.h" #include "tm.h"
#include "tm_p.h" #include "tm_p.h"
#include "cpplib.h" #include "cpplib.h"
#include "tree.h" #include "tree.h"
#include "c-family/c-common.h" #include "c-family/c-common.h"
/* Not included in avr.c since this requires C front end. */ /* Not included in avr.c since this requires C front end. */
/* Worker function for TARGET_CPU_CPP_BUILTINS. */ /* Worker function for TARGET_CPU_CPP_BUILTINS. */
void void
avr_cpu_cpp_builtins (struct cpp_reader *pfile) avr_cpu_cpp_builtins (struct cpp_reader *pfile)
{ {
builtin_define_std ("AVR"); builtin_define_std ("AVR");
if (avr_current_arch->macro) if (avr_current_arch->macro)
cpp_define (pfile, avr_current_arch->macro); cpp_define (pfile, avr_current_arch->macro);
if (avr_extra_arch_macro) if (avr_extra_arch_macro)
cpp_define (pfile, avr_extra_arch_macro); cpp_define (pfile, avr_extra_arch_macro);
if (avr_current_arch->have_elpm) if (avr_current_arch->have_elpm)
cpp_define (pfile, "__AVR_HAVE_RAMPZ__"); cpp_define (pfile, "__AVR_HAVE_RAMPZ__");
if (avr_current_arch->have_elpm) if (avr_current_arch->have_elpm)
cpp_define (pfile, "__AVR_HAVE_ELPM__"); cpp_define (pfile, "__AVR_HAVE_ELPM__");
if (avr_current_arch->have_elpmx) if (avr_current_arch->have_elpmx)
cpp_define (pfile, "__AVR_HAVE_ELPMX__"); cpp_define (pfile, "__AVR_HAVE_ELPMX__");
if (avr_current_arch->have_movw_lpmx) if (avr_current_arch->have_movw_lpmx)
{ {
cpp_define (pfile, "__AVR_HAVE_MOVW__"); cpp_define (pfile, "__AVR_HAVE_MOVW__");
cpp_define (pfile, "__AVR_HAVE_LPMX__"); cpp_define (pfile, "__AVR_HAVE_LPMX__");
} }
if (avr_current_arch->asm_only) if (avr_current_arch->asm_only)
cpp_define (pfile, "__AVR_ASM_ONLY__"); cpp_define (pfile, "__AVR_ASM_ONLY__");
if (avr_current_arch->have_mul) if (avr_current_arch->have_mul)
{ {
cpp_define (pfile, "__AVR_ENHANCED__"); cpp_define (pfile, "__AVR_ENHANCED__");
cpp_define (pfile, "__AVR_HAVE_MUL__"); cpp_define (pfile, "__AVR_HAVE_MUL__");
} }
if (avr_current_arch->have_jmp_call) if (avr_current_arch->have_jmp_call)
{ {
cpp_define (pfile, "__AVR_MEGA__"); cpp_define (pfile, "__AVR_MEGA__");
cpp_define (pfile, "__AVR_HAVE_JMP_CALL__"); cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
} }
if (avr_current_arch->have_eijmp_eicall) if (avr_current_arch->have_eijmp_eicall)
{ {
cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__"); cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
cpp_define (pfile, "__AVR_3_BYTE_PC__"); cpp_define (pfile, "__AVR_3_BYTE_PC__");
} }
else else
{ {
cpp_define (pfile, "__AVR_2_BYTE_PC__"); cpp_define (pfile, "__AVR_2_BYTE_PC__");
} }
if (avr_current_device->short_sp) if (avr_current_device->short_sp)
cpp_define (pfile, "__AVR_HAVE_8BIT_SP__"); cpp_define (pfile, "__AVR_HAVE_8BIT_SP__");
else else
cpp_define (pfile, "__AVR_HAVE_16BIT_SP__"); cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
if (TARGET_NO_INTERRUPTS) if (TARGET_NO_INTERRUPTS)
cpp_define (pfile, "__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");
}
}
...@@ -35,9 +35,6 @@ ...@@ -35,9 +35,6 @@
;; ~ Output 'r' if not AVR_HAVE_JMP_CALL. ;; ~ Output 'r' if not AVR_HAVE_JMP_CALL.
;; ! Output 'e' if AVR_HAVE_EIJMP_EICALL. ;; ! 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 (define_constants
[(REG_X 26) [(REG_X 26)
...@@ -50,17 +47,29 @@ ...@@ -50,17 +47,29 @@
(SREG_ADDR 0x5F) (SREG_ADDR 0x5F)
(RAMPZ_ADDR 0x5B) (RAMPZ_ADDR 0x5B)
])
(UNSPEC_STRLEN 0)
(UNSPEC_INDEX_JMP 1) (define_c_enum "unspec"
(UNSPEC_SEI 2) [UNSPEC_STRLEN
(UNSPEC_CLI 3) UNSPEC_INDEX_JMP
UNSPEC_FMUL
(UNSPECV_PROLOGUE_SAVES 0) UNSPEC_FMULS
(UNSPECV_EPILOGUE_RESTORES 1) UNSPEC_FMULSU
(UNSPECV_WRITE_SP_IRQ_ON 2) ])
(UNSPECV_WRITE_SP_IRQ_OFF 3)
(UNSPECV_GOTO_RECEIVER 4)]) (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 "predicates.md")
(include "constraints.md") (include "constraints.md")
...@@ -1489,7 +1498,7 @@ ...@@ -1489,7 +1498,7 @@
FAIL; FAIL;
}") }")
(define_insn "*rotlqi3_4" (define_insn "rotlqi3_4"
[(set (match_operand:QI 0 "register_operand" "=r") [(set (match_operand:QI 0 "register_operand" "=r")
(rotate:QI (match_operand:QI 1 "register_operand" "0") (rotate:QI (match_operand:QI 1 "register_operand" "0")
(const_int 4)))] (const_int 4)))]
...@@ -3130,21 +3139,19 @@ ...@@ -3130,21 +3139,19 @@
;; Enable Interrupts ;; Enable Interrupts
(define_insn "enable_interrupt" (define_insn "enable_interrupt"
[(unspec [(const_int 0)] UNSPEC_SEI)] [(unspec_volatile [(const_int 1)] UNSPECV_ENABLE_IRQS)]
"" ""
"sei" "sei"
[(set_attr "length" "1") [(set_attr "length" "1")
(set_attr "cc" "none") (set_attr "cc" "none")])
])
;; Disable Interrupts ;; Disable Interrupts
(define_insn "disable_interrupt" (define_insn "disable_interrupt"
[(unspec [(const_int 0)] UNSPEC_CLI)] [(unspec_volatile [(const_int 0)] UNSPECV_ENABLE_IRQS)]
"" ""
"cli" "cli"
[(set_attr "length" "1") [(set_attr "length" "1")
(set_attr "cc" "none") (set_attr "cc" "none")])
])
;; Library prologue saves ;; Library prologue saves
(define_insn "call_prologue_saves" (define_insn "call_prologue_saves"
...@@ -3246,3 +3253,138 @@ ...@@ -3246,3 +3253,138 @@
expand_epilogue (true /* sibcall_p */); expand_epilogue (true /* sibcall_p */);
DONE; 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")])
...@@ -7924,6 +7924,7 @@ instructions, but allow the compiler to schedule those calls. ...@@ -7924,6 +7924,7 @@ instructions, but allow the compiler to schedule those calls.
* Alpha Built-in Functions:: * Alpha Built-in Functions::
* ARM iWMMXt Built-in Functions:: * ARM iWMMXt Built-in Functions::
* ARM NEON Intrinsics:: * ARM NEON Intrinsics::
* AVR Built-in Functions::
* Blackfin Built-in Functions:: * Blackfin Built-in Functions::
* FR-V Built-in Functions:: * FR-V Built-in Functions::
* X86 Built-in Functions:: * X86 Built-in Functions::
...@@ -8175,6 +8176,44 @@ when the @option{-mfpu=neon} switch is used: ...@@ -8175,6 +8176,44 @@ when the @option{-mfpu=neon} switch is used:
@include arm-neon-intrinsics.texi @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 @node Blackfin Built-in Functions
@subsection Blackfin Built-in Functions @subsection Blackfin Built-in Functions
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment