git subrepo clone https://github.com/libretro/libretro-common.git deps/libretro-common
[pcsx_rearmed.git] / deps / libretro-common / libco / armeabi.c
CommitLineData
3719602c
PC
1/*
2 libco.armeabi (2013-04-05)
3 author: Themaister
4 license: public domain
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
19extern "C" {
20#endif
21
22static thread_local uint32_t co_active_buffer[64];
23static thread_local cothread_t co_active_handle;
24
25__asm__ (
26#if defined(__thumb2__)
27 ".align 2\n"
28 ".globl co_switch_arm\n"
29 ".globl _co_switch_arm\n"
30 ".thumb\n"
31 ".thumb_func\n"
32 ".type co_switch_arm, %function\n"
33 ".type _co_switch_arm, %function\n"
34 "co_switch_arm:\n"
35 "_co_switch_arm:\n"
36 " mov r3, sp\n"
37 " stmia r1!, {r4, r5, r6, r7, r8, r9, r10, r11}\n"
38 " stmia r1!, {r3, lr}\n"
39 " ldmia r0!, {r4, r5, r6, r7, r8, r9, r10, r11}\n"
40 " ldmfd r0!, { r3 }\n"
41 " mov sp, r3\n"
42 " ldmfd r0!, { r3 }\n"
43 " mov pc, r3\n"
44#else
45 ".arm\n"
46 ".align 4\n"
47 ".globl co_switch_arm\n"
48 ".globl _co_switch_arm\n"
49 "co_switch_arm:\n"
50 "_co_switch_arm:\n"
51 " stmia r1!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, lr}\n"
52 " ldmia r0!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, pc}\n"
53#endif
54 );
55
56/* ASM */
57void co_switch_arm(cothread_t handle, cothread_t current);
58
59cothread_t co_create(unsigned int size, void (*entrypoint)(void))
60{
61 uint32_t *ptr = NULL;
62 cothread_t handle = 0;
63 size = (size + 1023) & ~1023;
64#if defined(__APPLE__) || HAVE_POSIX_MEMALIGN >= 1
65 if (posix_memalign(&handle, 1024, size + 256) < 0)
66 return 0;
67#else
68 handle = memalign(1024, size + 256);
69#endif
70
71 if (!handle)
72 return handle;
73
74 ptr = (uint32_t*)handle;
75 /* Non-volatiles. */
76 ptr[0] = 0; /* r4 */
77 ptr[1] = 0; /* r5 */
78 ptr[2] = 0; /* r6 */
79 ptr[3] = 0; /* r7 */
80 ptr[4] = 0; /* r8 */
81 ptr[5] = 0; /* r9 */
82 ptr[6] = 0; /* r10 */
83 ptr[7] = 0; /* r11 */
84 /* Align stack to 64-bit */
85 ptr[8] = (uintptr_t)ptr + size + 256 - 8; /* r13, stack pointer */
86 ptr[9] = (uintptr_t)entrypoint; /* r15, PC (link register r14 gets saved here). */
87 return handle;
88}
89
90cothread_t co_active(void)
91{
92 if (!co_active_handle)
93 co_active_handle = co_active_buffer;
94 return co_active_handle;
95}
96
97void co_delete(cothread_t handle)
98{
99 free(handle);
100}
101
102void co_switch(cothread_t handle)
103{
104 cothread_t co_previous_handle = co_active();
105 co_switch_arm(co_active_handle = handle, co_previous_handle);
106}
107
108#ifdef __cplusplus
109}
110#endif