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
48struct 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/*--------------------------------------------------------------------------*/
73void
74cooja_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/*--------------------------------------------------------------------------*/
95static struct cooja_mtarch_thread *cooja_running_thread;
96/*--------------------------------------------------------------------------*/
97void 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/*--------------------------------------------------------------------------*/
173void
174cooja_mtarch_exec(struct cooja_mtarch_thread *t)
175{
176 cooja_running_thread = t;
177 cooja_sw();
178 cooja_running_thread = NULL;
179}
180/*--------------------------------------------------------------------------*/
181void
182cooja_mtarch_yield(void)
183{
184 cooja_sw();
185}
186/*--------------------------------------------------------------------------*/