Skip to content

Commit 75dd774

Browse files
committed
libco mips
1 parent 5baa0fc commit 75dd774

2 files changed

Lines changed: 162 additions & 1 deletion

File tree

libco/libco.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ void genode_free_secondary_stack(void *stack);
2929
#include "ppc.c"
3030
#elif defined(__aarch64__)
3131
#include "aarch64.c"
32-
#elif defined(PSP)
32+
#elif defined PSP
3333
#include "psp1.c"
3434
#elif defined VITA
3535
#include "scefiber.c"
36+
#elif defined(__mips__)
37+
#include "mips.c"
3638
#elif defined(__ARM_EABI__) || defined(__arm__)
3739
#include "armeabi.c"
3840
#else

libco/mips.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
libco.mips (2020-04-20)
3+
author: Google
4+
license: MIT
5+
*/
6+
7+
#define LIBCO_C
8+
#include <libco.h>
9+
#include <assert.h>
10+
#include <stdlib.h>
11+
#include <string.h>
12+
#include <stdint.h>
13+
14+
#ifndef __APPLE__
15+
#include <malloc.h>
16+
#endif
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
static thread_local uint64_t co_active_buffer[64];
23+
static thread_local cothread_t co_active_handle;
24+
25+
#if __mips >= 3
26+
/* If we have 64-bit registers. */
27+
#define STORE_REG "sd"
28+
#define LOAD_REG "ld"
29+
#define REG_TRANSFORM(x) (x)
30+
#else
31+
/* 32-bit only variant. */
32+
#define STORE_REG "sw"
33+
#define LOAD_REG "lw"
34+
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
35+
#define REG_TRANSFORM(x) (((uint64_t)(x)) << 64)
36+
#else
37+
#define REG_TRANSFORM(x) (x)
38+
#endif
39+
#endif
40+
#define HAVE_FP 1
41+
42+
__asm__ (
43+
".align 4\n"
44+
".globl co_switch_mips\n"
45+
".globl _co_switch_mips\n"
46+
"co_switch_mips:\n"
47+
"_co_switch_mips:\n"
48+
STORE_REG " $s0, 0($a1)\n"
49+
STORE_REG " $s1, 8($a1)\n"
50+
STORE_REG " $s2, 0x10($a1)\n"
51+
STORE_REG " $s3, 0x18($a1)\n"
52+
STORE_REG " $s4, 0x20($a1)\n"
53+
STORE_REG " $s5, 0x28($a1)\n"
54+
STORE_REG " $s6, 0x30($a1)\n"
55+
STORE_REG " $s7, 0x38($a1)\n"
56+
STORE_REG " $gp, 0x40($a1)\n"
57+
STORE_REG " $sp, 0x48($a1)\n"
58+
STORE_REG " $fp, 0x50($a1)\n"
59+
STORE_REG " $ra, 0x58($a1)\n"
60+
#if HAVE_FP
61+
" swc1 $f20, 0x60($a1)\n"
62+
" swc1 $f21, 0x64($a1)\n"
63+
" swc1 $f22, 0x68($a1)\n"
64+
" swc1 $f23, 0x6c($a1)\n"
65+
" swc1 $f24, 0x70($a1)\n"
66+
" swc1 $f25, 0x74($a1)\n"
67+
" swc1 $f26, 0x78($a1)\n"
68+
" swc1 $f27, 0x7c($a1)\n"
69+
" swc1 $f28, 0x80($a1)\n"
70+
" swc1 $f29, 0x84($a1)\n"
71+
" swc1 $f30, 0x88($a1)\n"
72+
#endif
73+
LOAD_REG " $s0, 0($a0)\n"
74+
LOAD_REG " $s1, 8($a0)\n"
75+
LOAD_REG " $s2, 0x10($a0)\n"
76+
LOAD_REG " $s3, 0x18($a0)\n"
77+
LOAD_REG " $s4, 0x20($a0)\n"
78+
LOAD_REG " $s5, 0x28($a0)\n"
79+
LOAD_REG " $s6, 0x30($a0)\n"
80+
LOAD_REG " $s7, 0x38($a0)\n"
81+
LOAD_REG " $gp, 0x40($a0)\n"
82+
LOAD_REG " $sp, 0x48($a0)\n"
83+
LOAD_REG " $fp, 0x50($a0)\n"
84+
LOAD_REG " $ra, 0x58($a0)\n"
85+
#if HAVE_FP
86+
" lwc1 $f20, 0x60($a0)\n"
87+
" lwc1 $f21, 0x64($a0)\n"
88+
" lwc1 $f22, 0x68($a0)\n"
89+
" lwc1 $f23, 0x6c($a0)\n"
90+
" lwc1 $f24, 0x70($a0)\n"
91+
" lwc1 $f25, 0x74($a0)\n"
92+
" lwc1 $f26, 0x78($a0)\n"
93+
" lwc1 $f27, 0x7c($a0)\n"
94+
" lwc1 $f28, 0x80($a0)\n"
95+
" lwc1 $f29, 0x84($a0)\n"
96+
" lwc1 $f30, 0x88($a0)\n"
97+
#endif
98+
" jr $ra\n"
99+
" nop\n"
100+
".align 4\n"
101+
".globl store_gp\n"
102+
".globl _store_gp\n"
103+
"store_gp:\n"
104+
"_store_gp:\n"
105+
STORE_REG " $gp, 0($a0)\n"
106+
" jr $ra\n"
107+
" nop\n"
108+
);
109+
110+
/* ASM */
111+
void co_switch_mips(cothread_t handle, cothread_t current);
112+
void store_gp(uint64_t *s);
113+
114+
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
115+
{
116+
size = (size + 1023) & ~1023;
117+
cothread_t handle = 0;
118+
#if defined(__APPLE__) || HAVE_POSIX_MEMALIGN >= 1
119+
if (posix_memalign(&handle, 1024, size + 512) < 0)
120+
return 0;
121+
#else
122+
handle = memalign(1024, size + 512);
123+
#endif
124+
125+
if (!handle)
126+
return handle;
127+
128+
uint64_t *ptr = (uint64_t*)handle;
129+
memset(ptr, 0, 512);
130+
/* Non-volatiles. */
131+
/* ptr[0],..., ptr[7] -> s0,..., s7 */
132+
store_gp(&ptr[8]); /* gp */
133+
ptr[9] = REG_TRANSFORM(((uintptr_t)ptr + size + 512 - 8)); /* sp */
134+
/* ptr[10] is fp */
135+
ptr[11] = REG_TRANSFORM((uintptr_t)entrypoint); /* ra */
136+
return handle;
137+
}
138+
139+
cothread_t co_active(void)
140+
{
141+
if (!co_active_handle)
142+
co_active_handle = co_active_buffer;
143+
return co_active_handle;
144+
}
145+
146+
void co_delete(cothread_t handle)
147+
{
148+
free(handle);
149+
}
150+
151+
void co_switch(cothread_t handle)
152+
{
153+
cothread_t co_previous_handle = co_active();
154+
co_switch_mips(co_active_handle = handle, co_previous_handle);
155+
}
156+
157+
#ifdef __cplusplus
158+
}
159+
#endif

0 commit comments

Comments
 (0)