1 /*
2 * Copyright (c) 2013 Google Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23 #include <compiler.h>
24 #include <kernel/debug.h>
25
26 __ALIGNED(8) __NAKED
27 #if (__CORTEX_M >= 0x03) || (CORTEX_SC >= 300)
28
spin_cycles(uint32_t cycles)29 void spin_cycles(uint32_t cycles)
30 {
31 asm (
32 /* 4 cycles per loop, subtract out 8 cycles for the overhead of the next
33 * 4 instructions, plus the call into and return from the function.
34 * Then, add 3 then >> 2 to round up to the number of loop iterations.
35 */
36 "subs r1, %[cycles], #5\n"
37 "asrs r1, r1, #2\n"
38 "ble .Ldone\n"
39
40 /* Padding to stay aligned on an 8 byte boundary, also has the added
41 * advantage of normalizing the overhead (1+1+2 cycles if the branch is
42 * take, or 1+1+1+1 cycles if the branch is skipped and the nop is
43 * executed)
44 */
45 "nop\n"
46
47 /* Main delay loop.
48 * sub is 1 cycle
49 * nop is 1 cycle
50 * branch is 2 cycles
51 */
52 ".Lloop:\n"
53 "subs r1, r1, #1\n"
54 "nop\n"
55 "bne .Lloop\n"
56
57 ".Ldone:\n"
58 "bx lr\n"
59 : /* no output */
60 : [cycles] "r" (cycles) /* input is cycles */
61 : "r1" /* r1 gets clobbered */
62 );
63 }
64
65 #else
66 /* Cortex-M0 & Cortex-M0+ */
67 void spin_cycles(uint32_t cycles)
68 {
69 asm (
70 /* 4 cycles per loop, subtract out 8 cycles for the overhead of the next
71 * 4 instructions, plus the call into and return from the function.
72 * Then, add 3 then >> 2 to round up to the number of loop iterations.
73 */
74 "sub r1, %[cycles], #5\n"
75 "asr r1, r1, #2\n"
76 "cmp r1, #0\n"
77 "ble .Ldone\n"
78
79 /* Padding to stay aligned on an 8 byte boundary, also has the added
80 * advantage of normalizing the overhead (1+1+2 cycles if the branch is
81 * take, or 1+1+1+1 cycles if the branch is skipped and the nop is
82 * executed)
83 */
84 "nop\n"
85
86 /* Main delay loop.
87 * sub is 1 cycle
88 * nop is 1 cycle
89 * branch is 2 cycles
90 */
91 ".Lloop:\n"
92 "sub r1, r1, #1\n"
93 "cmp r1,#0\n"
94 "bne .Lloop\n"
95
96 ".Ldone:\n"
97 "bx lr\n"
98 : /* no output */
99 : [cycles] "r" (cycles) /* input is cycles */
100 : "r1" /* r1 gets clobbered */
101 );
102 }
103 #endif
104