PR inline-asm/84742
[official-gcc.git] / gcc / testsuite / gcc.target / msp430 / msp_abi_div_funcs.c
blobc125ac60c5ad4eedf4b591469ea2a870d96cf6d4
1 /* { dg-do run } */
2 /* { dg-options "-std=c99" } */
4 extern int printf (const char *, ...);
5 extern void abort (void) __attribute__((noreturn));
7 typedef unsigned long uint32;
8 typedef unsigned long long uint64;
10 extern uint32 __mspabi_divul (uint32, uint32);
11 extern uint32 __mspabi_divlu (uint32, uint32);
12 extern uint64 __mspabi_divull (uint64, uint64);
13 extern uint64 __mspabi_divllu (uint64, uint64);
15 uint32 func1 (uint32, uint32) __attribute__ ((noinline));
16 uint32 func2 (uint32, uint32) __attribute__ ((noinline));
17 uint32 func3 (uint32, uint32) __attribute__ ((noinline));
18 uint64 func4 (uint64, uint64) __attribute__ ((noinline));
19 uint64 func5 (uint64, uint64) __attribute__ ((noinline));
20 uint64 func6 (uint64, uint64) __attribute__ ((noinline));
23 #define DEBUG 0
25 int
26 main (void)
28 int fail = 0;
30 if (func1 (7UL, 3UL) != 2UL)
32 #if DEBUG
33 printf ("FAIL: func1: 7 / 3 returns %lu\n", func1 (7UL, 3UL));
34 #endif
35 ++ fail;
38 if (func2 (7UL, 3UL) != 2UL)
40 #if DEBUG
41 printf ("FAIL: func2: 7 / 3 returns %lu\n", func2 (7UL, 3UL));
42 #endif
43 ++ fail;
46 if (func3 (7UL, 3UL) != 2UL)
48 #if DEBUG
49 printf ("FAIL: func4: 7 / 3 returns %lu\n", func3 (7UL, 3UL));
50 #endif
51 ++ fail;
54 if (func4 (7ULL, 3ULL) != 2ULL)
56 #if DEBUG
57 printf ("FAIL: func4: 7 / 3 returns %llu\n", func4 (7ULL, 3ULL));
58 #endif
59 ++ fail;
62 if (func5 (7ULL, 3ULL) != 2ULL)
64 #if DEBUG
65 printf ("FAIL: func5: 7 / 3 returns %llu\n", func5 (7ULL, 3ULL));
66 #endif
67 ++ fail;
70 if (func6 (7ULL, 3ULL) != 2ULL)
72 #if DEBUG
73 printf ("FAIL: func6: 7 / 3 returns %llu\n", func6 (7ULL, 3ULL));
74 #endif
75 ++ fail;
78 if (fail)
79 abort ();
81 return 0;
84 /* At high levels of optimization gcc will probably fold func1 and func4 into
85 main, but this does not really matter. Those two functions are just there
86 for a sanity check at low levels of optimization. */
88 uint32 func1 (uint32 a, uint32 b) { return a / b; }
89 uint32 func2 (uint32 a, uint32 b) { return __mspabi_divul (a, b); }
90 uint32 func3 (uint32 a, uint32 b) { return __mspabi_divlu (a, b); }
91 uint64 func4 (uint64 a, uint64 b) { return a / b; }
92 uint64 func5 (uint64 a, uint64 b) { return __mspabi_divull (a, b); }
94 uint64
95 func6 (uint64 a, uint64 b)
97 uint64 ret;
99 /* This test function is special. The correctly spelt ABI function
100 __mspabi_divull takes its first argument in registers R8::R11 and its
101 second argument in registers R12::R15, but GCC knows that __mspabi_divllu
102 is not the correct spelling and so it will use the normal function
103 calling convention - first argument in R12::R15, second argument on the
104 stack.
106 The stub function for __mspabi_divllu in libgcc just does a BRAnch to
107 the real __mspabi_divull function - it does *not* rearrange the arguments
108 or pull anything off the stack. This is correct, because in real code
109 that calls __mspabi_divllu, compiled by *old* versions of gcc, the
110 arguments will already be in the special ABI mandated locations.
112 As a result, in order to test __mspabi_divllu here, we have to put the
113 arguments into the correct registers ourselves and call __mspabi_divllu
114 manually. This does lead to some very inefficient code generation, but
115 that is not our concern here. */
117 #ifdef __MSP430X_LARGE__
118 __asm ("mov %A1, r8\n\
119 mov %B1, r9\n\
120 mov %C1, r10\n\
121 mov %D1, r11\n\
122 mov %A2, r12\n\
123 mov %B2, r13\n\
124 mov %C2, r14\n\
125 mov %D2, r15\n\
126 calla #__mspabi_divllu\n\
127 mov r12, %A0\n\
128 mov r13, %B0\n\
129 mov r14, %C0\n\
130 mov r15, %D0\n"
131 : "=r" (ret) : "r" (a), "m" (b));
132 #else
133 __asm ("mov %A1, r8\n\
134 mov %B1, r9\n\
135 mov %C1, r10\n\
136 mov %D1, r11\n\
137 mov %A2, r12\n\
138 mov %B2, r13\n\
139 mov %C2, r14\n\
140 mov %D2, r15\n\
141 call #__mspabi_divllu\n\
142 mov r12, %A0\n\
143 mov r13, %B0\n\
144 mov r14, %C0\n\
145 mov r15, %D0\n"
146 : "=r" (ret) : "r" (a), "m" (b));
147 #endif
149 return ret;