add riscv32 port
parent
464f98a01b
commit
1ad20e03e5
|
@ -25,6 +25,7 @@ target to do it.
|
||||||
| mips64 | ✓ | | ✓ | |
|
| mips64 | ✓ | | ✓ | |
|
||||||
| ppc | ✓ | ✓ | | |
|
| ppc | ✓ | ✓ | | |
|
||||||
| ppc64 | ✓ | ✓ | | |
|
| ppc64 | ✓ | ✓ | | |
|
||||||
|
| riscv32 | ✓ | | ✓ | ✓ |
|
||||||
| riscv64 | ✓ | | ✓ | ✓ |
|
| riscv64 | ✓ | | ✓ | ✓ |
|
||||||
| s390x | ✓ | | ✓ | |
|
| s390x | ✓ | | ✓ | |
|
||||||
| sh | ✓ | | ✓ | ✓ |
|
| sh | ✓ | | ✓ | ✓ |
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef __ARCH_RISCV64_DEFS_H
|
||||||
|
#define __ARCH_RISCV64_DEFS_H
|
||||||
|
|
||||||
|
#define REG_SZ (4)
|
||||||
|
#define MCONTEXT_GREGS (160)
|
||||||
|
|
||||||
|
/* program counter is saved in x0 as well as x1, similar to mips */
|
||||||
|
#ifndef REG_PC
|
||||||
|
#define REG_PC (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef REG_RA
|
||||||
|
#define REG_RA (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef REG_SP
|
||||||
|
#define REG_SP (2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef REG_S0
|
||||||
|
#define REG_S0 (8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REG_S1 (9)
|
||||||
|
|
||||||
|
#ifndef REG_A0
|
||||||
|
#define REG_A0 (10)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define REG_A1 (11)
|
||||||
|
#define REG_A2 (12)
|
||||||
|
#define REG_A3 (13)
|
||||||
|
#define REG_A4 (14)
|
||||||
|
#define REG_A5 (15)
|
||||||
|
#define REG_A6 (16)
|
||||||
|
#define REG_A7 (17)
|
||||||
|
#define REG_S2 (18)
|
||||||
|
#define REG_S3 (19)
|
||||||
|
#define REG_S4 (20)
|
||||||
|
#define REG_S5 (21)
|
||||||
|
#define REG_S6 (22)
|
||||||
|
#define REG_S7 (23)
|
||||||
|
#define REG_S8 (24)
|
||||||
|
#define REG_S9 (25)
|
||||||
|
#define REG_S10 (26)
|
||||||
|
#define REG_S11 (27)
|
||||||
|
|
||||||
|
#define PC_OFFSET REG_OFFSET(REG_PC)
|
||||||
|
|
||||||
|
#define FETCH_LINKPTR(dest) \
|
||||||
|
asm("mv %0, s1" : "=r" ((dest)))
|
||||||
|
|
||||||
|
#include "common-defs.h"
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* This software is provided 'as is' and without any warranty, express or
|
||||||
|
* implied. In no event shall the authors be liable for any damages arising
|
||||||
|
* from the use of this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
ALIAS(getcontext, libucontext_getcontext)
|
||||||
|
ALIAS(__getcontext, libucontext_getcontext)
|
||||||
|
|
||||||
|
FUNC(libucontext_getcontext)
|
||||||
|
sw ra, REG_OFFSET(REG_PC)(a0)
|
||||||
|
sw ra, REG_OFFSET(REG_RA)(a0)
|
||||||
|
sw sp, REG_OFFSET(REG_SP)(a0)
|
||||||
|
|
||||||
|
/* first saved register block */
|
||||||
|
sw s0, REG_OFFSET(REG_S0)(a0)
|
||||||
|
sw s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
|
/* return register block */
|
||||||
|
sw a0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sw a1, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
|
/* second saved register block */
|
||||||
|
sw s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
sw s3, REG_OFFSET(REG_S3)(a0)
|
||||||
|
sw s4, REG_OFFSET(REG_S4)(a0)
|
||||||
|
sw s5, REG_OFFSET(REG_S5)(a0)
|
||||||
|
sw s6, REG_OFFSET(REG_S6)(a0)
|
||||||
|
sw s7, REG_OFFSET(REG_S7)(a0)
|
||||||
|
sw s8, REG_OFFSET(REG_S8)(a0)
|
||||||
|
sw s9, REG_OFFSET(REG_S9)(a0)
|
||||||
|
sw s10, REG_OFFSET(REG_S10)(a0)
|
||||||
|
sw s11, REG_OFFSET(REG_S11)(a0)
|
||||||
|
|
||||||
|
/* done saving, return */
|
||||||
|
ret
|
||||||
|
END(libucontext_getcontext)
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef LIBUCONTEXT_BITS_H
|
||||||
|
#define LIBUCONTEXT_BITS_H
|
||||||
|
|
||||||
|
typedef unsigned long libucontext_greg_t;
|
||||||
|
typedef unsigned long libucontext__riscv_mc_gp_state[32];
|
||||||
|
|
||||||
|
struct libucontext__riscv_mc_f_ext_state {
|
||||||
|
unsigned int __f[32];
|
||||||
|
unsigned int __fcsr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libucontext__riscv_mc_d_ext_state {
|
||||||
|
unsigned long long __f[32];
|
||||||
|
unsigned int __fcsr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libucontext__riscv_mc_q_ext_state {
|
||||||
|
unsigned long long __f[64] __attribute__((aligned(16)));
|
||||||
|
unsigned int __fcsr;
|
||||||
|
unsigned int __reserved[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
union libucontext__riscv_mc_fp_state {
|
||||||
|
struct libucontext__riscv_mc_f_ext_state __f;
|
||||||
|
struct libucontext__riscv_mc_d_ext_state __d;
|
||||||
|
struct libucontext__riscv_mc_q_ext_state __q;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct libucontext_mcontext {
|
||||||
|
libucontext__riscv_mc_gp_state __gregs;
|
||||||
|
union libucontext__riscv_mc_fp_state __fpregs;
|
||||||
|
} libucontext_mcontext_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *ss_sp;
|
||||||
|
int ss_flags;
|
||||||
|
size_t ss_size;
|
||||||
|
} libucontext_stack_t;
|
||||||
|
|
||||||
|
typedef struct libucontext_ucontext {
|
||||||
|
unsigned long uc_flags;
|
||||||
|
struct libucontext_ucontext *uc_link;
|
||||||
|
libucontext_stack_t uc_stack;
|
||||||
|
unsigned char __pad[128];
|
||||||
|
libucontext_mcontext_t uc_mcontext;
|
||||||
|
} libucontext_ucontext_t;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* This software is provided 'as is' and without any warranty, express or
|
||||||
|
* implied. In no event shall the authors be liable for any damages arising
|
||||||
|
* from the use of this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GNU_SOURCE
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#endif
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern void libucontext_trampoline(void);
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
libucontext_makecontext(libucontext_ucontext_t *ucp, void (*func)(void), int argc, ...)
|
||||||
|
{
|
||||||
|
libucontext_greg_t *sp, *regp;
|
||||||
|
va_list va;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* set up and align the stack. */
|
||||||
|
sp = (libucontext_greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
|
||||||
|
sp -= argc < 8 ? 0 : argc - 8;
|
||||||
|
sp = (libucontext_greg_t *) (((uintptr_t) sp & -16L));
|
||||||
|
|
||||||
|
/* set up the ucontext structure */
|
||||||
|
ucp->uc_mcontext.__gregs[REG_RA] = (libucontext_greg_t) libucontext_trampoline;
|
||||||
|
ucp->uc_mcontext.__gregs[REG_S0] = 0;
|
||||||
|
ucp->uc_mcontext.__gregs[REG_S1] = (libucontext_greg_t) ucp->uc_link;
|
||||||
|
ucp->uc_mcontext.__gregs[REG_SP] = (libucontext_greg_t) sp;
|
||||||
|
ucp->uc_mcontext.__gregs[REG_PC] = (libucontext_greg_t) func;
|
||||||
|
|
||||||
|
va_start(va, argc);
|
||||||
|
|
||||||
|
/* first 8 args go in $a0 through $a7. */
|
||||||
|
regp = &(ucp->uc_mcontext.__gregs[REG_A0]);
|
||||||
|
|
||||||
|
for (i = 0; (i < argc && i < 8); i++)
|
||||||
|
*regp++ = va_arg (va, libucontext_greg_t);
|
||||||
|
|
||||||
|
/* remainder overflows into stack */
|
||||||
|
for (; i < argc; i++)
|
||||||
|
*sp++ = va_arg (va, libucontext_greg_t);
|
||||||
|
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EXPORT_UNPREFIXED
|
||||||
|
extern __typeof(libucontext_makecontext) makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
extern __typeof(libucontext_makecontext) __makecontext __attribute__((weak, __alias__("libucontext_makecontext")));
|
||||||
|
#endif
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* This software is provided 'as is' and without any warranty, express or
|
||||||
|
* implied. In no event shall the authors be liable for any damages arising
|
||||||
|
* from the use of this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
ALIAS(setcontext, libucontext_setcontext)
|
||||||
|
ALIAS(__setcontext, libucontext_setcontext)
|
||||||
|
|
||||||
|
FUNC(libucontext_setcontext)
|
||||||
|
/* move $a0 to $t0 to avoid clobbering. */
|
||||||
|
mv t0, a0
|
||||||
|
|
||||||
|
lw t1, PC_OFFSET(t0)
|
||||||
|
lw ra, REG_OFFSET(REG_RA)(t0)
|
||||||
|
lw sp, REG_OFFSET(REG_SP)(t0)
|
||||||
|
|
||||||
|
/* first saved register block */
|
||||||
|
lw s0, REG_OFFSET(REG_S0)(t0)
|
||||||
|
lw s1, REG_OFFSET(REG_S1)(t0)
|
||||||
|
|
||||||
|
/* return register block */
|
||||||
|
lw a0, REG_OFFSET(REG_A0)(t0)
|
||||||
|
lw a1, REG_OFFSET(REG_A1)(t0)
|
||||||
|
|
||||||
|
/* argument register block */
|
||||||
|
lw a2, REG_OFFSET(REG_A2)(t0)
|
||||||
|
lw a3, REG_OFFSET(REG_A3)(t0)
|
||||||
|
lw a4, REG_OFFSET(REG_A4)(t0)
|
||||||
|
lw a5, REG_OFFSET(REG_A5)(t0)
|
||||||
|
lw a6, REG_OFFSET(REG_A6)(t0)
|
||||||
|
lw a7, REG_OFFSET(REG_A7)(t0)
|
||||||
|
|
||||||
|
/* second saved register block */
|
||||||
|
lw s2, REG_OFFSET(REG_S2)(t0)
|
||||||
|
lw s3, REG_OFFSET(REG_S3)(t0)
|
||||||
|
lw s4, REG_OFFSET(REG_S4)(t0)
|
||||||
|
lw s5, REG_OFFSET(REG_S5)(t0)
|
||||||
|
lw s6, REG_OFFSET(REG_S6)(t0)
|
||||||
|
lw s7, REG_OFFSET(REG_S7)(t0)
|
||||||
|
lw s8, REG_OFFSET(REG_S8)(t0)
|
||||||
|
lw s9, REG_OFFSET(REG_S9)(t0)
|
||||||
|
lw s10, REG_OFFSET(REG_S10)(t0)
|
||||||
|
lw s11, REG_OFFSET(REG_S11)(t0)
|
||||||
|
|
||||||
|
/* done restoring, jump to new pc in S1 */
|
||||||
|
jr t1
|
||||||
|
END(libucontext_setcontext)
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Ariadne Conill <ariadne@dereferenced.org>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* This software is provided 'as is' and without any warranty, express or
|
||||||
|
* implied. In no event shall the authors be liable for any damages arising
|
||||||
|
* from the use of this software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
ALIAS(swapcontext, libucontext_swapcontext)
|
||||||
|
ALIAS(__swapcontext, libucontext_swapcontext)
|
||||||
|
|
||||||
|
FUNC(libucontext_swapcontext)
|
||||||
|
/* move $a1 to $t0 to avoid clobbering. */
|
||||||
|
mv t0, a1
|
||||||
|
|
||||||
|
sw ra, REG_OFFSET(REG_PC)(a0)
|
||||||
|
sw ra, REG_OFFSET(REG_RA)(a0)
|
||||||
|
sw sp, REG_OFFSET(REG_SP)(a0)
|
||||||
|
|
||||||
|
/* first saved register block */
|
||||||
|
sw s0, REG_OFFSET(REG_S0)(a0)
|
||||||
|
sw s1, REG_OFFSET(REG_S1)(a0)
|
||||||
|
|
||||||
|
/* return register block */
|
||||||
|
sw a0, REG_OFFSET(REG_A0)(a0)
|
||||||
|
sw a1, REG_OFFSET(REG_A1)(a0)
|
||||||
|
|
||||||
|
/* second saved register block */
|
||||||
|
sw s2, REG_OFFSET(REG_S2)(a0)
|
||||||
|
sw s3, REG_OFFSET(REG_S3)(a0)
|
||||||
|
sw s4, REG_OFFSET(REG_S4)(a0)
|
||||||
|
sw s5, REG_OFFSET(REG_S5)(a0)
|
||||||
|
sw s6, REG_OFFSET(REG_S6)(a0)
|
||||||
|
sw s7, REG_OFFSET(REG_S7)(a0)
|
||||||
|
sw s8, REG_OFFSET(REG_S8)(a0)
|
||||||
|
sw s9, REG_OFFSET(REG_S9)(a0)
|
||||||
|
sw s10, REG_OFFSET(REG_S10)(a0)
|
||||||
|
sw s11, REG_OFFSET(REG_S11)(a0)
|
||||||
|
|
||||||
|
/* restore the other context from $t0. */
|
||||||
|
lw t1, REG_OFFSET(REG_PC)(t0)
|
||||||
|
lw ra, REG_OFFSET(REG_RA)(t0)
|
||||||
|
lw sp, REG_OFFSET(REG_SP)(t0)
|
||||||
|
|
||||||
|
/* first saved register block */
|
||||||
|
lw s0, REG_OFFSET(REG_S0)(t0)
|
||||||
|
lw s1, REG_OFFSET(REG_S1)(t0)
|
||||||
|
|
||||||
|
/* return register block */
|
||||||
|
lw a0, REG_OFFSET(REG_A0)(t0)
|
||||||
|
lw a1, REG_OFFSET(REG_A1)(t0)
|
||||||
|
|
||||||
|
/* argument register block */
|
||||||
|
lw a2, REG_OFFSET(REG_A2)(t0)
|
||||||
|
lw a3, REG_OFFSET(REG_A3)(t0)
|
||||||
|
lw a4, REG_OFFSET(REG_A4)(t0)
|
||||||
|
lw a5, REG_OFFSET(REG_A5)(t0)
|
||||||
|
lw a6, REG_OFFSET(REG_A6)(t0)
|
||||||
|
lw a7, REG_OFFSET(REG_A7)(t0)
|
||||||
|
|
||||||
|
/* second saved register block */
|
||||||
|
lw s2, REG_OFFSET(REG_S2)(t0)
|
||||||
|
lw s3, REG_OFFSET(REG_S3)(t0)
|
||||||
|
lw s4, REG_OFFSET(REG_S4)(t0)
|
||||||
|
lw s5, REG_OFFSET(REG_S5)(t0)
|
||||||
|
lw s6, REG_OFFSET(REG_S6)(t0)
|
||||||
|
lw s7, REG_OFFSET(REG_S7)(t0)
|
||||||
|
lw s8, REG_OFFSET(REG_S8)(t0)
|
||||||
|
lw s9, REG_OFFSET(REG_S9)(t0)
|
||||||
|
lw s10, REG_OFFSET(REG_S10)(t0)
|
||||||
|
lw s11, REG_OFFSET(REG_S11)(t0)
|
||||||
|
|
||||||
|
/* done swapping, jump to new PC in S1 */
|
||||||
|
jr t1
|
||||||
|
END(libucontext_swapcontext)
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "defs.h"
|
||||||
|
#include <libucontext/libucontext.h>
|
||||||
|
#include "common-trampoline.c"
|
Loading…
Reference in New Issue