add riscv32 port
parent
464f98a01b
commit
1ad20e03e5
|
@ -25,6 +25,7 @@ target to do it.
|
|||
| mips64 | ✓ | | ✓ | |
|
||||
| ppc | ✓ | ✓ | | |
|
||||
| ppc64 | ✓ | ✓ | | |
|
||||
| riscv32 | ✓ | | ✓ | ✓ |
|
||||
| riscv64 | ✓ | | ✓ | ✓ |
|
||||
| s390x | ✓ | | ✓ | |
|
||||
| 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