aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/msp430/msp430.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2014-05-14 17:27:21 -0400
committerDJ Delorie <dj@gcc.gnu.org>2014-05-14 17:27:21 -0400
commit5f35dde552bfb56e7517e4e0fd0b90acad08347a (patch)
tree6164dc3c18ebd6f66884acadd7a0ee343469b3ba /gcc/config/msp430/msp430.c
parent5d40b20f6efeace2533cd594fa782d55859b1d9f (diff)
downloadgcc-5f35dde552bfb56e7517e4e0fd0b90acad08347a.zip
gcc-5f35dde552bfb56e7517e4e0fd0b90acad08347a.tar.gz
gcc-5f35dde552bfb56e7517e4e0fd0b90acad08347a.tar.bz2
msp430.c (msp430_builtin): Add MSP430_BUILTIN_DELAY_CYCLES.
* config/msp430/msp430.c (msp430_builtin): Add MSP430_BUILTIN_DELAY_CYCLES. (msp430_init_builtins): Register void __delay_cycles(long long). (msp430_builtin_decl): Add it. (cg_magic_constant): New. (msp430_expand_delay_cycles): New. (msp430_expand_builtin): Call it. (msp430_print_operand_raw): Change integer printing from "int" to HOST_WIDE_INT. * config/msp430/msp430.md (define_constants): Add delay_cycles tags. (delay_cycles_start): New. (delay_cycles_end): New. (delay_cycles_32): New. (delay_cycles_32x): New. (delay_cycles_16): New. (delay_cycles_16x): New. (delay_cycles_2): New. (delay_cycles_1): New. * doc/extend.texi: Document __delay_cycles(). From-SVN: r210441
Diffstat (limited to 'gcc/config/msp430/msp430.c')
-rw-r--r--gcc/config/msp430/msp430.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c
index 1ec9652..55b6f0b 100644
--- a/gcc/config/msp430/msp430.c
+++ b/gcc/config/msp430/msp430.c
@@ -1194,6 +1194,7 @@ enum msp430_builtin
{
MSP430_BUILTIN_BIC_SR,
MSP430_BUILTIN_BIS_SR,
+ MSP430_BUILTIN_DELAY_CYCLES,
MSP430_BUILTIN_max
};
@@ -1203,6 +1204,7 @@ static void
msp430_init_builtins (void)
{
tree void_ftype_int = build_function_type_list (void_type_node, integer_type_node, NULL);
+ tree void_ftype_longlong = build_function_type_list (void_type_node, long_long_integer_type_node, NULL);
msp430_builtins[MSP430_BUILTIN_BIC_SR] =
add_builtin_function ( "__bic_SR_register_on_exit", void_ftype_int,
@@ -1211,6 +1213,10 @@ msp430_init_builtins (void)
msp430_builtins[MSP430_BUILTIN_BIS_SR] =
add_builtin_function ( "__bis_SR_register_on_exit", void_ftype_int,
MSP430_BUILTIN_BIS_SR, BUILT_IN_MD, NULL, NULL_TREE);
+
+ msp430_builtins[MSP430_BUILTIN_DELAY_CYCLES] =
+ add_builtin_function ( "__delay_cycles", void_ftype_longlong,
+ MSP430_BUILTIN_DELAY_CYCLES, BUILT_IN_MD, NULL, NULL_TREE);
}
static tree
@@ -1220,12 +1226,126 @@ msp430_builtin_decl (unsigned code, bool initialize ATTRIBUTE_UNUSED)
{
case MSP430_BUILTIN_BIC_SR:
case MSP430_BUILTIN_BIS_SR:
+ case MSP430_BUILTIN_DELAY_CYCLES:
return msp430_builtins[code];
default:
return error_mark_node;
}
}
+/* These constants are really register reads, which are faster than
+ regular constants. */
+static int
+cg_magic_constant (HOST_WIDE_INT c)
+{
+ switch (c)
+ {
+ case 0xffff:
+ case -1:
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static rtx
+msp430_expand_delay_cycles (rtx arg)
+{
+ HOST_WIDE_INT i, c, n;
+ /* extra cycles for MSP430X instructions */
+#define CYCX(M,X) (msp430x ? (X) : (M))
+
+ if (GET_CODE (arg) != CONST_INT)
+ {
+ error ("__delay_cycles() only takes constant arguments");
+ return NULL_RTX;
+ }
+
+ c = INTVAL (arg);
+
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ {
+ if (c < 0)
+ {
+ error ("__delay_cycles only takes non-negative cycle counts.");
+ return NULL_RTX;
+ }
+ }
+
+ emit_insn (gen_delay_cycles_start (arg));
+
+ /* For 32-bit loops, there's 13(16) + 5(min(x,0x10000) + 6x cycles. */
+ if (c > 3 * 0xffff + CYCX (7, 10))
+ {
+ n = c;
+ /* There's 4 cycles in the short (i>0xffff) loop and 7 in the long (x<=0xffff) loop */
+ if (c >= 0x10000 * 7 + CYCX (14, 16))
+ {
+ i = 0x10000;
+ c -= CYCX (14, 16) + 7 * 0x10000;
+ i += c / 4;
+ c %= 4;
+ if ((unsigned long long) i > 0xffffffffULL)
+ {
+ error ("__delay_cycles is limited to 32-bit loop counts.");
+ return NULL_RTX;
+ }
+ }
+ else
+ {
+ i = (c - CYCX (14, 16)) / 7;
+ c -= CYCX (14, 16) + i * 7;
+ }
+
+ if (cg_magic_constant (i & 0xffff))
+ c ++;
+ if (cg_magic_constant ((i >> 16) & 0xffff))
+ c ++;
+
+ if (msp430x)
+ emit_insn (gen_delay_cycles_32x (GEN_INT (i), GEN_INT (n - c)));
+ else
+ emit_insn (gen_delay_cycles_32 (GEN_INT (i), GEN_INT (n - c)));
+ }
+
+ /* For 16-bit loops, there's 7(10) + 3x cycles - so the max cycles is 0x30004(7). */
+ if (c > 12)
+ {
+ n = c;
+ i = (c - CYCX (7, 10)) / 3;
+ c -= CYCX (7, 10) + i * 3;
+
+ if (cg_magic_constant (i))
+ c ++;
+
+ if (msp430x)
+ emit_insn (gen_delay_cycles_16x (GEN_INT (i), GEN_INT (n - c)));
+ else
+ emit_insn (gen_delay_cycles_16 (GEN_INT (i), GEN_INT (n - c)));
+ }
+
+ while (c > 1)
+ {
+ emit_insn (gen_delay_cycles_2 ());
+ c -= 2;
+ }
+
+ if (c)
+ {
+ emit_insn (gen_delay_cycles_1 ());
+ c -= 1;
+ }
+
+ emit_insn (gen_delay_cycles_end (arg));
+
+ return NULL_RTX;
+}
+
static rtx
msp430_expand_builtin (tree exp,
rtx target ATTRIBUTE_UNUSED,
@@ -1237,6 +1357,9 @@ msp430_expand_builtin (tree exp,
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
rtx arg1 = expand_normal (CALL_EXPR_ARG (exp, 0));
+ if (fcode == MSP430_BUILTIN_DELAY_CYCLES)
+ return msp430_expand_delay_cycles (arg1);
+
if (! msp430_is_interrupt_func ())
{
error ("MSP430 builtin functions only work inside interrupt handlers");