summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-04-13 20:55:48 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-04-13 20:55:48 +0000
commitd95c39072ace1a7aeaad3ee49ed668399b4862bd (patch)
tree7f8c8e41e5e793daa64051f153bbbd52ccbe8fc9
parente10f455fbd3149a034e35d30be333f958d773d92 (diff)
downloadrockbox-d95c39072ace1a7aeaad3ee49ed668399b4862bd.tar.gz
rockbox-d95c39072ace1a7aeaad3ee49ed668399b4862bd.zip
Portal Player: Add invalidate_icache and flush_icache. Flush the cache on the core for newborn threads. In doing so, move more ARM stuff to the target tree and organize it to make a clean job of it. If anything isn't appropriate for some particular device give a hollar or even just fix it by some added #ifdefing. I was informed that the PP targets are register compatible so I'm going off that advice. The Sansa likes it though.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13144 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/system.h165
-rw-r--r--firmware/rolo.c6
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h (renamed from firmware/target/arm/gigabeat/meg-fx/system-target.h)1
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c14
-rw-r--r--firmware/target/arm/system-pp.h49
-rw-r--r--firmware/target/arm/system-target.h155
-rw-r--r--firmware/target/coldfire/system-target.h4
-rw-r--r--firmware/thread.c47
8 files changed, 262 insertions, 179 deletions
diff --git a/firmware/export/system.h b/firmware/export/system.h
index b32d1d3a21..19ce7a4d6a 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -29,24 +29,6 @@ extern void system_init(void);
29 29
30extern long cpu_frequency; 30extern long cpu_frequency;
31 31
32#ifdef CPU_PP
33#define inl(a) (*(volatile unsigned long *) (a))
34#define outl(a,b) (*(volatile unsigned long *) (b) = (a))
35#define inb(a) (*(volatile unsigned char *) (a))
36#define outb(a,b) (*(volatile unsigned char *) (b) = (a))
37#define inw(a) (*(volatile unsigned short *) (a))
38#define outw(a,b) (*(volatile unsigned short *) (b) = (a))
39extern unsigned int ipod_hw_rev;
40
41static inline void udelay(unsigned usecs)
42{
43 unsigned stop = USEC_TIMER + usecs;
44 while (TIME_BEFORE(USEC_TIMER, stop));
45}
46
47unsigned int current_core(void);
48#endif
49
50struct flash_header { 32struct flash_header {
51 unsigned long magic; 33 unsigned long magic;
52 unsigned long length; 34 unsigned long length;
@@ -173,10 +155,6 @@ int get_cpu_boost_counter(void);
173#define H_TO_BE32(x) (x) 155#define H_TO_BE32(x) (x)
174#endif 156#endif
175 157
176
177#define nop \
178 asm volatile ("nop")
179
180/* gcc 3.4 changed the format of the constraints */ 158/* gcc 3.4 changed the format of the constraints */
181#if (__GNUC__ >= 3) && (__GNUC_MINOR__ > 3) || (__GNUC__ >= 4) 159#if (__GNUC__ >= 3) && (__GNUC_MINOR__ > 3) || (__GNUC__ >= 4)
182#define I_CONSTRAINT "I08" 160#define I_CONSTRAINT "I08"
@@ -196,141 +174,7 @@ enum {
196}; 174};
197 175
198#ifndef SIMULATOR 176#ifndef SIMULATOR
199#if defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440) || (CONFIG_CPU == SH7034)
200#include "system-target.h" 177#include "system-target.h"
201#endif
202#endif
203
204#ifndef SIMULATOR
205
206#if defined(CPU_ARM)
207
208/* TODO: Implement set_irq_level and check CPU frequencies */
209
210#if CONFIG_CPU == S3C2440
211
212#define CPUFREQ_DEFAULT 98784000
213#define CPUFREQ_NORMAL 98784000
214#define CPUFREQ_MAX 296352000
215
216#elif CONFIG_CPU == PNX0101
217
218#define CPUFREQ_DEFAULT 12000000
219#define CPUFREQ_NORMAL 48000000
220#define CPUFREQ_MAX 60000000
221
222#else
223
224#define CPUFREQ_DEFAULT_MULT 8
225#define CPUFREQ_DEFAULT 24000000
226#define CPUFREQ_NORMAL_MULT 10
227#define CPUFREQ_NORMAL 30000000
228#define CPUFREQ_MAX_MULT 25
229#define CPUFREQ_MAX 75000000
230
231#endif
232
233static inline uint16_t swap16(uint16_t value)
234 /*
235 result[15..8] = value[ 7..0];
236 result[ 7..0] = value[15..8];
237 */
238{
239 return (value >> 8) | (value << 8);
240}
241
242static inline uint32_t swap32(uint32_t value)
243 /*
244 result[31..24] = value[ 7.. 0];
245 result[23..16] = value[15.. 8];
246 result[15.. 8] = value[23..16];
247 result[ 7.. 0] = value[31..24];
248 */
249{
250 uint32_t tmp;
251
252 asm volatile (
253 "eor %1, %0, %0, ror #16 \n\t"
254 "bic %1, %1, #0xff0000 \n\t"
255 "mov %0, %0, ror #8 \n\t"
256 "eor %0, %0, %1, lsr #8 \n\t"
257 : "+r" (value), "=r" (tmp)
258 );
259 return value;
260}
261
262static inline uint32_t swap_odd_even32(uint32_t value)
263{
264 /*
265 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
266 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
267 */
268 uint32_t tmp;
269
270 asm volatile ( /* ABCD */
271 "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
272 "bic %0, %0, #0xff0000 \n\t" /* A.CD */
273 "mov %0, %0, lsr #8 \n\t" /* .A.C */
274 "orr %0, %0, %1, lsl #8 \n\t" /* B.D.|.A.C */
275 : "+r" (value), "=r" (tmp) /* BADC */
276 );
277 return value;
278}
279
280#define HIGHEST_IRQ_LEVEL (1)
281
282static inline int set_irq_level(int level)
283{
284 unsigned long cpsr;
285 /* Read the old level and set the new one */
286 asm volatile ("mrs %0,cpsr" : "=r" (cpsr));
287 asm volatile ("msr cpsr_c,%0"
288 : : "r" ((cpsr & ~0x80) | (level << 7)));
289 return (cpsr >> 7) & 1;
290}
291
292static inline void set_fiq_handler(void(*fiq_handler)(void))
293{
294 /* Install the FIQ handler */
295 *((unsigned int*)(15*4)) = (unsigned int)fiq_handler;
296}
297
298static inline void enable_fiq(void)
299{
300 /* Clear FIQ disable bit */
301 asm volatile (
302 "mrs r0, cpsr \n"\
303 "bic r0, r0, #0x40 \n"\
304 "msr cpsr_c, r0 "
305 : : : "r0"
306 );
307}
308
309static inline void disable_fiq(void)
310{
311 /* Set FIQ disable bit */
312 asm volatile (
313 "mrs r0, cpsr \n"\
314 "orr r0, r0, #0x40 \n"\
315 "msr cpsr_c, r0 "
316 : : : "r0"
317 );
318}
319
320#if CONFIG_CPU != S3C2440
321#define invalidate_icache()
322#endif
323
324#if CONFIG_CPU == PNX0101
325typedef void (*interrupt_handler_t)(void);
326
327void irq_set_int_handler(int n, interrupt_handler_t handler);
328void irq_enable_int(int n);
329void irq_disable_int(int n);
330#endif
331
332#endif
333
334#else /* SIMULATOR */ 178#else /* SIMULATOR */
335 179
336static inline uint16_t swap16(uint16_t value) 180static inline uint16_t swap16(uint16_t value)
@@ -365,8 +209,15 @@ static inline uint32_t swap_odd_even32(uint32_t value)
365 return (t >> 8) | ((t ^ value) << 8); 209 return (t >> 8) | ((t ^ value) << 8);
366} 210}
367 211
212#endif /* !SIMULATOR */
213
214/* Just define these as empty if not declared */
215#ifndef HAVE_INVALIDATE_ICACHE
368#define invalidate_icache() 216#define invalidate_icache()
217#endif
369 218
370#endif /* !SIMULATOR */ 219#ifndef HAVE_FLUSH_ICACHE
220#define flush_icache()
221#endif
371 222
372#endif /* __SYSTEM_H__ */ 223#endif /* __SYSTEM_H__ */
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 0689e8be5b..0375a7ac82 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -49,8 +49,7 @@ void rolo_restart_cop(void) ICODE_ATTR;
49void rolo_restart_cop(void) 49void rolo_restart_cop(void)
50{ 50{
51 /* Invalidate cache */ 51 /* Invalidate cache */
52 outl(inl(0xf000f044) | 0x6, 0xf000f044); 52 invalidate_icache();
53 while ((CACHE_CTL & 0x8000) != 0) {}
54 53
55 /* Disable cache */ 54 /* Disable cache */
56 CACHE_CTL = CACHE_DISABLE; 55 CACHE_CTL = CACHE_DISABLE;
@@ -119,8 +118,7 @@ void rolo_restart(const unsigned char* source, unsigned char* dest,
119 cpu_message = 0; 118 cpu_message = 0;
120 119
121 /* Flush cache */ 120 /* Flush cache */
122 outl(inl(0xf000f044) | 0x2, 0xf000f044); 121 flush_icache();
123 while ((CACHE_CTL & 0x8000) != 0) {}
124 122
125 /* Disable cache */ 123 /* Disable cache */
126 CACHE_CTL = CACHE_DISABLE; 124 CACHE_CTL = CACHE_DISABLE;
diff --git a/firmware/target/arm/gigabeat/meg-fx/system-target.h b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h
index e5d15d643e..7d598af360 100644
--- a/firmware/target/arm/gigabeat/meg-fx/system-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h
@@ -19,6 +19,7 @@
19 19
20#include "mmu-meg-fx.h" 20#include "mmu-meg-fx.h"
21 21
22#define HAVE_INVALIDATE_ICACHE
22static inline void invalidate_icache(void) 23static inline void invalidate_icache(void)
23{ 24{
24 clean_dcache(); 25 clean_dcache();
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index 3e8246b367..93d79633b1 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -112,16 +112,6 @@ static inline void lcd_write_reg(unsigned int reg, unsigned int data)
112 lcd_send_msg(0x72, data); 112 lcd_send_msg(0x72, data);
113} 113}
114 114
115static inline void cache_flush(void)
116{
117#ifndef BOOTLOADER
118 outl(inl(0xf000f044) | 0x2, 0xf000f044);
119 while ((CACHE_CTL & 0x8000) != 0)
120 {
121 }
122#endif
123}
124
125/* The LCD controller gets passed the address of the framebuffer, but can only 115/* The LCD controller gets passed the address of the framebuffer, but can only
126 use the physical, not the remapped, address. This is a quick and dirty way 116 use the physical, not the remapped, address. This is a quick and dirty way
127 of correcting it */ 117 of correcting it */
@@ -271,7 +261,7 @@ inline void lcd_update_rect(int x, int y, int width, int height)
271 memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), 261 memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
272 ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH), 262 ((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
273 ((height * sizeof(fb_data) * LCD_WIDTH))); 263 ((height * sizeof(fb_data) * LCD_WIDTH)));
274 cache_flush(); 264 flush_icache();
275 265
276 /* Restart DMA */ 266 /* Restart DMA */
277 LCD_REG_6 |= 1; 267 LCD_REG_6 |= 1;
@@ -287,7 +277,7 @@ inline void lcd_update(void)
287 277
288 /* Copy the Rockbox framebuffer to the second framebuffer */ 278 /* Copy the Rockbox framebuffer to the second framebuffer */
289 memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT); 279 memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
290 cache_flush(); 280 flush_icache();
291 281
292 /* Restart DMA */ 282 /* Restart DMA */
293 LCD_REG_6 |= 1; 283 LCD_REG_6 |= 1;
diff --git a/firmware/target/arm/system-pp.h b/firmware/target/arm/system-pp.h
new file mode 100644
index 0000000000..05fd8b6edf
--- /dev/null
+++ b/firmware/target/arm/system-pp.h
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 * Copyright (C) 2007 by Michael Sevakis
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#define inl(a) (*(volatile unsigned long *) (a))
22#define outl(a,b) (*(volatile unsigned long *) (b) = (a))
23#define inb(a) (*(volatile unsigned char *) (a))
24#define outb(a,b) (*(volatile unsigned char *) (b) = (a))
25#define inw(a) (*(volatile unsigned short *) (a))
26#define outw(a,b) (*(volatile unsigned short *) (b) = (a))
27extern unsigned int ipod_hw_rev;
28
29static inline void udelay(unsigned usecs)
30{
31 unsigned stop = USEC_TIMER + usecs;
32 while (TIME_BEFORE(USEC_TIMER, stop));
33}
34
35unsigned int current_core(void);
36
37#define HAVE_INVALIDATE_ICACHE
38static inline void invalidate_icache(void)
39{
40 outl(inl(0xf000f044) | 0x6, 0xf000f044);
41 while ((CACHE_CTL & 0x8000) != 0);
42}
43
44#define HAVE_FLUSH_ICACHE
45static inline void flush_icache(void)
46{
47 outl(inl(0xf000f044) | 0x2, 0xf000f044);
48 while ((CACHE_CTL & 0x8000) != 0);
49}
diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h
new file mode 100644
index 0000000000..ceb8be2079
--- /dev/null
+++ b/firmware/target/arm/system-target.h
@@ -0,0 +1,155 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#ifndef SYSTEM_TARGET_H
20#define SYSTEM_TARGET_H
21
22#define nop \
23 asm volatile ("nop")
24
25/* This gets too complicated otherwise with all the ARM variation and would
26 have conflicts with another system-target.h elsewhere so include a
27 subheader from here. */
28
29#ifdef CPU_PP
30#include "system-pp.h"
31#elif CONFIG_CPU == S3C2440
32#include "system-meg-fx.h"
33#endif
34
35/* TODO: Implement set_irq_level and check CPU frequencies */
36
37#if CONFIG_CPU == S3C2440
38
39#define CPUFREQ_DEFAULT 98784000
40#define CPUFREQ_NORMAL 98784000
41#define CPUFREQ_MAX 296352000
42
43#elif CONFIG_CPU == PNX0101
44
45#define CPUFREQ_DEFAULT 12000000
46#define CPUFREQ_NORMAL 48000000
47#define CPUFREQ_MAX 60000000
48
49#else
50
51#define CPUFREQ_DEFAULT_MULT 8
52#define CPUFREQ_DEFAULT 24000000
53#define CPUFREQ_NORMAL_MULT 10
54#define CPUFREQ_NORMAL 30000000
55#define CPUFREQ_MAX_MULT 25
56#define CPUFREQ_MAX 75000000
57
58#endif
59
60static inline uint16_t swap16(uint16_t value)
61 /*
62 result[15..8] = value[ 7..0];
63 result[ 7..0] = value[15..8];
64 */
65{
66 return (value >> 8) | (value << 8);
67}
68
69static inline uint32_t swap32(uint32_t value)
70 /*
71 result[31..24] = value[ 7.. 0];
72 result[23..16] = value[15.. 8];
73 result[15.. 8] = value[23..16];
74 result[ 7.. 0] = value[31..24];
75 */
76{
77 uint32_t tmp;
78
79 asm volatile (
80 "eor %1, %0, %0, ror #16 \n\t"
81 "bic %1, %1, #0xff0000 \n\t"
82 "mov %0, %0, ror #8 \n\t"
83 "eor %0, %0, %1, lsr #8 \n\t"
84 : "+r" (value), "=r" (tmp)
85 );
86 return value;
87}
88
89static inline uint32_t swap_odd_even32(uint32_t value)
90{
91 /*
92 result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
93 result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
94 */
95 uint32_t tmp;
96
97 asm volatile ( /* ABCD */
98 "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
99 "bic %0, %0, #0xff0000 \n\t" /* A.CD */
100 "mov %0, %0, lsr #8 \n\t" /* .A.C */
101 "orr %0, %0, %1, lsl #8 \n\t" /* B.D.|.A.C */
102 : "+r" (value), "=r" (tmp) /* BADC */
103 );
104 return value;
105}
106
107#define HIGHEST_IRQ_LEVEL (1)
108
109static inline int set_irq_level(int level)
110{
111 unsigned long cpsr;
112 /* Read the old level and set the new one */
113 asm volatile ("mrs %0,cpsr" : "=r" (cpsr));
114 asm volatile ("msr cpsr_c,%0"
115 : : "r" ((cpsr & ~0x80) | (level << 7)));
116 return (cpsr >> 7) & 1;
117}
118
119static inline void set_fiq_handler(void(*fiq_handler)(void))
120{
121 /* Install the FIQ handler */
122 *((unsigned int*)(15*4)) = (unsigned int)fiq_handler;
123}
124
125static inline void enable_fiq(void)
126{
127 /* Clear FIQ disable bit */
128 asm volatile (
129 "mrs r0, cpsr \n"\
130 "bic r0, r0, #0x40 \n"\
131 "msr cpsr_c, r0 "
132 : : : "r0"
133 );
134}
135
136static inline void disable_fiq(void)
137{
138 /* Set FIQ disable bit */
139 asm volatile (
140 "mrs r0, cpsr \n"\
141 "orr r0, r0, #0x40 \n"\
142 "msr cpsr_c, r0 "
143 : : : "r0"
144 );
145}
146
147#if CONFIG_CPU == PNX0101
148typedef void (*interrupt_handler_t)(void);
149
150void irq_set_int_handler(int n, interrupt_handler_t handler);
151void irq_enable_int(int n);
152void irq_disable_int(int n);
153#endif
154
155#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 40542353be..6f1b2eb4ae 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -19,6 +19,9 @@
19#ifndef SYSTEM_TARGET_H 19#ifndef SYSTEM_TARGET_H
20#define SYSTEM_TARGET_H 20#define SYSTEM_TARGET_H
21 21
22#define nop \
23 asm volatile ("trapf")
24
22#define or_l(mask, address) \ 25#define or_l(mask, address) \
23 asm \ 26 asm \
24 ("or.l %0,(%1)" \ 27 ("or.l %0,(%1)" \
@@ -147,6 +150,7 @@ static inline uint32_t swap_odd_even32(uint32_t value)
147 return value; 150 return value;
148} 151}
149 152
153#define HAVE_INVALIDATE_ICACHE
150static inline void invalidate_icache(void) 154static inline void invalidate_icache(void)
151{ 155{
152 asm volatile ("move.l #0x01000000,%d0\n" 156 asm volatile ("move.l #0x01000000,%d0\n"
diff --git a/firmware/thread.c b/firmware/thread.c
index a803e4f78d..275f04d029 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -64,12 +64,15 @@ int *cop_stackend = stackend;
64#endif 64#endif
65 65
66#if NUM_CORES > 1 66#if NUM_CORES > 1
67#if 0
67static long cores_locked IBSS_ATTR; 68static long cores_locked IBSS_ATTR;
68 69
69#define LOCK(...) do { } while (test_and_set(&cores_locked, 1)) 70#define LOCK(...) do { } while (test_and_set(&cores_locked, 1))
70#define UNLOCK(...) cores_locked = 0 71#define UNLOCK(...) cores_locked = 0
72#endif
71 73
72#warning "Core locking mechanism should be fixed on H10/4G!" 74#warning "Core locking mechanism should be fixed on H10/4G!"
75
73inline void lock_cores(void) 76inline void lock_cores(void)
74{ 77{
75#if 0 78#if 0
@@ -125,15 +128,47 @@ static inline void store_context(void* addr)
125 * Load non-volatile context. 128 * Load non-volatile context.
126 *--------------------------------------------------------------------------- 129 *---------------------------------------------------------------------------
127 */ 130 */
131static void start_thread(void (*thread_func)(void), const void* addr) __attribute__((naked));
132static void start_thread(void (*thread_func)(void), const void* addr)
133{
134 /* r0 = thread_func, r1 = addr */
135#if NUM_CORES > 1
136 asm volatile (
137 "mov r2, #0 \n"
138 "str r2, [r1, #40] \n"
139 "ldr r1, =0xf000f044 \n" /* invalidate this core's cache */
140 "ldr r2, [r1] \n"
141 "orr r2, r2, #6 \n"
142 "str r2, [r1] \n"
143 "ldr r1, =0x6000c000 \n"
144 "1: \n"
145 "ldr r2, [r1] \n"
146 "tst r2, #0x8000 \n"
147 "bne 1b \n"
148 "mov pc, r0 \n"
149 : : : "r1", "r2"
150 );
151#else
152 asm volatile (
153 "mov r2, #0 \n"
154 "str r2, [r1, #40] \n"
155 "mov pc, r0 \n"
156 : : : "r1", "r2"
157 );
158#endif
159 (void)thread_func;
160 (void)addr;
161 (void)start_thread;
162}
163
128static inline void load_context(const void* addr) 164static inline void load_context(const void* addr)
129{ 165{
130 asm volatile( 166 asm volatile(
131 "ldmia %0, { r4-r11, sp, lr }\n" /* load regs r4 to r14 from context */ 167 "ldmia %0, { r4-r11, sp, lr } \n" /* load regs r4 to r14 from context */
132 "ldr r0, [%0, #40] \n" /* load start pointer */ 168 "ldr r0, [%0, #40] \n" /* load start pointer */
133 "mov r1, #0 \n" 169 "cmp r0, #0 \n" /* check for NULL */
134 "cmp r0, r1 \n" /* check for NULL */ 170 "movne r1, %0 \n" /* if not already running, jump to start */
135 "strne r1, [%0, #40] \n" /* if it's NULL, we're already running */ 171 "ldrne pc, =start_thread \n"
136 "movne pc, r0 \n" /* not already running, so jump to start */
137 : : "r" (addr) : "r0", "r1" 172 : : "r" (addr) : "r0", "r1"
138 ); 173 );
139} 174}