Contiki-NG
cooja_mtarch.c
1 /*
2  * Copyright (c) 2005, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 #include <stddef.h>
34 
35 #include <limits.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include "sys/cooja_mt.h"
39 
40 #if INTPTR_MAX == INT32_MAX
41 #define ON_64BIT_ARCH 0
42 #elif INTPTR_MAX == INT64_MAX
43 #define ON_64BIT_ARCH 1
44 #else
45 #error "Could not detect 32/64-bit environment."
46 #endif
47 
48 struct frame {
49  uintptr_t flags;
50 #if ON_64BIT_ARCH
51  uintptr_t rbp;
52  uintptr_t rdi;
53  uintptr_t rsi;
54  uintptr_t rdx;
55  uintptr_t rcx;
56  uintptr_t rbx;
57  uintptr_t rax;
58 #else /* ON_64BIT_ARCH */
59  uintptr_t ebp;
60  uintptr_t edi;
61  uintptr_t esi;
62  uintptr_t edx;
63  uintptr_t ecx;
64  uintptr_t ebx;
65  uintptr_t eax;
66 #endif /* ON_64BIT_ARCH */
67  uintptr_t retaddr;
68  uintptr_t retaddr2;
69  uintptr_t data;
70 };
71 
72 /*--------------------------------------------------------------------------*/
73 void
74 cooja_mtarch_start(struct cooja_mtarch_thread *t,
75  void (*function)(void *), void *data)
76 {
77  struct frame *f = (struct frame *)&t->stack[COOJA_MTARCH_STACKSIZE - sizeof(struct frame)/sizeof(uintptr_t)];
78  int i;
79 
80  for(i = 0; i < COOJA_MTARCH_STACKSIZE; ++i) {
81  t->stack[i] = i;
82  }
83 
84  memset(f, 0, sizeof(struct frame));
85  f->retaddr = (uintptr_t)function;
86  f->data = (uintptr_t)data;
87  t->sp = (uintptr_t)&f->flags;
88 #if ON_64BIT_ARCH
89  f->rbp = (uintptr_t)&f->rax;
90 #else /* ON_64BIT_ARCH */
91  f->ebp = (uintptr_t)&f->eax;
92 #endif /* ON_64BIT_ARCH */
93 }
94 /*--------------------------------------------------------------------------*/
95 static struct cooja_mtarch_thread *cooja_running_thread;
96 /*--------------------------------------------------------------------------*/
97 void cooja_sw(void)
98 {
99  /* Store registers */
100 #if ON_64BIT_ARCH
101  __asm__ (
102  "pushq %rax\n\t"
103  "pushq %rbx\n\t"
104  "pushq %rcx\n\t"
105  "pushq %rdx\n\t"
106  "pushq %rsi\n\t"
107  "pushq %rdi\n\t"
108  "pushq %rbp\n\t"
109  "pushq %rbp\n\t");
110 #else /* ON_64BIT_ARCH */
111  __asm__ (
112  "pushl %eax\n\t"
113  "pushl %ebx\n\t"
114  "pushl %ecx\n\t"
115  "pushl %edx\n\t"
116  "pushl %esi\n\t"
117  "pushl %edi\n\t"
118  "pushl %ebp\n\t"
119  "pushl %ebp\n\t");
120 #endif /* ON_64BIT_ARCH */
121 
122  /* Switch stack pointer */
123 #if ON_64BIT_ARCH
124  __asm__ ("movq %0, %%rax\n\t" : : "m" (cooja_running_thread));
125  __asm__ (
126  "movq (%rax), %rbx\n\t"
127  "movq %rsp, (%rax)\n\t"
128  "movq %rbx, %rsp\n\t"
129  );
130 #else /* ON_64BIT_ARCH */
131  __asm__ ("movl %0, %%eax\n\t" : : "m" (cooja_running_thread));
132  __asm__ (
133  "movl (%eax), %ebx\n\t"
134  "movl %esp, (%eax)\n\t"
135  "movl %ebx, %esp\n\t"
136  );
137 #endif /* ON_64BIT_ARCH */
138 
139  /* Restore previous registers */
140 #if ON_64BIT_ARCH
141  __asm__ (
142  "popq %rbp\n\t"
143  "popq %rbp\n\t"
144  "popq %rdi\n\t"
145  "popq %rsi\n\t"
146  "popq %rdx\n\t"
147  "popq %rcx\n\t"
148  "popq %rbx\n\t"
149  "popq %rax\n\t"
150 
151  "leave\n\t"
152  "ret\n\t"
153  );
154 #else /* ON_64BIT_ARCH */
155  __asm__ (
156  "popl %ebp\n\t"
157  "popl %ebp\n\t"
158  "popl %edi\n\t"
159  "popl %esi\n\t"
160  "popl %edx\n\t"
161  "popl %ecx\n\t"
162  "popl %ebx\n\t"
163  "popl %eax\n\t"
164 
165  "leave\n\t"
166  "ret\n\t"
167  );
168 #endif /* ON_64BIT_ARCH */
169 
170 }
171 
172 /*--------------------------------------------------------------------------*/
173 void
174 cooja_mtarch_exec(struct cooja_mtarch_thread *t)
175 {
176  cooja_running_thread = t;
177  cooja_sw();
178  cooja_running_thread = NULL;
179 }
180 /*--------------------------------------------------------------------------*/
181 void
182 cooja_mtarch_yield(void)
183 {
184  cooja_sw();
185 }
186 /*--------------------------------------------------------------------------*/