riscv64: Add skeleton target

This commit is contained in:
Michael Matz 2019-06-22 06:13:10 +02:00
parent 9e429dbef0
commit 0676d5bc23
10 changed files with 435 additions and 22 deletions

View File

@ -78,6 +78,7 @@ NATIVE_DEFINES_$(CONFIG_arm_eabihf) += -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
NATIVE_DEFINES_$(CONFIG_arm_eabi) += -DTCC_ARM_EABI
NATIVE_DEFINES_$(CONFIG_arm_vfp) += -DTCC_ARM_VFP
NATIVE_DEFINES_$(CONFIG_arm64) += -DTCC_TARGET_ARM64
NATIVE_DEFINES_$(CONFIG_riscv64) += -DTCC_TARGET_RISCV64
NATIVE_DEFINES += $(NATIVE_DEFINES_yes)
ifeq ($(INCLUDED),no)
@ -92,10 +93,12 @@ all: $(PROGS) $(TCCLIBS) $(TCCDOCS)
# cross compiler targets to build
TCC_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince c67
TCC_X += riscv64
# TCC_X += arm-fpa arm-fpa-ld arm-vfp arm-eabi
# cross libtcc1.a targets to build
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
LIBTCC1_X = riscv64
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)
@ -133,6 +136,7 @@ DEF-arm-vfp = -DTCC_TARGET_ARM -DTCC_ARM_VFP
DEF-arm-eabi = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI
DEF-arm-eabihf = -DTCC_TARGET_ARM -DTCC_ARM_VFP -DTCC_ARM_EABI -DTCC_ARM_HARDFLOAT
DEF-arm = $(DEF-arm-eabihf)
DEF-riscv64 = -DTCC_TARGET_RISCV64
DEF-$(NATIVE_TARGET) = $(NATIVE_DEFINES)
DEFINES += $(DEF-$T) $(DEF-all)
@ -172,6 +176,7 @@ arm-eabi_FILES = $(arm_FILES)
arm-eabihf_FILES = $(arm_FILES)
arm64_FILES = $(CORE_FILES) arm64-gen.c arm64-link.c
c67_FILES = $(CORE_FILES) c67-gen.c c67-link.c tcccoff.c
riscv64_FILES = $(CORE_FILES) riscv64-gen.c riscv64-link.c
# libtcc sources
LIBTCC_SRC = $(filter-out tcc.c tcctools.c,$(filter %.c,$($T_FILES)))

3
configure vendored
View File

@ -232,6 +232,9 @@ case "$cpu" in
s390)
cpu="s390"
;;
riscv64)
cpu="riscv64"
;;
*)
echo "Unsupported CPU"
exit 1

View File

@ -13,6 +13,8 @@
# define TRIPLET_ARCH "arm"
#elif defined(__aarch64__)
# define TRIPLET_ARCH "aarch64"
#elif defined(__riscv) && defined(__LP64__)
# define TRIPLET_ARCH "riscv64"
#else
# define TRIPLET_ARCH "unknown"
#endif

71
elf.h
View File

@ -262,7 +262,8 @@ typedef struct
#define EM_AARCH64 183 /* ARM AARCH64 */
#define EM_TILEPRO 188 /* Tilera TILEPro */
#define EM_TILEGX 191 /* Tilera TILE-Gx */
#define EM_NUM 192
#define EM_RISCV 243 /* RISC-V */
#define EM_NUM 253
/* If it is necessary to assign new unofficial EM_* values, please
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
@ -381,7 +382,7 @@ typedef struct
#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
#define SHF_ORDERED (1 << 30) /* Special ordering requirement
(Solaris). */
#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless
#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
referenced or allocated (Solaris).*/
/* Section group handling. */
@ -3233,5 +3234,71 @@ typedef Elf32_Addr Elf32_Conflict;
#define R_TILEGX_NUM 130
/* RISC-V ELF Flags */
#define EF_RISCV_RVC 0x0001
#define EF_RISCV_FLOAT_ABI 0x0006
#define EF_RISCV_FLOAT_ABI_SOFT 0x0000
#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
/* RISC-V relocations. */
#define R_RISCV_NONE 0
#define R_RISCV_32 1
#define R_RISCV_64 2
#define R_RISCV_RELATIVE 3
#define R_RISCV_COPY 4
#define R_RISCV_JUMP_SLOT 5
#define R_RISCV_TLS_DTPMOD32 6
#define R_RISCV_TLS_DTPMOD64 7
#define R_RISCV_TLS_DTPREL32 8
#define R_RISCV_TLS_DTPREL64 9
#define R_RISCV_TLS_TPREL32 10
#define R_RISCV_TLS_TPREL64 11
#define R_RISCV_BRANCH 16
#define R_RISCV_JAL 17
#define R_RISCV_CALL 18
#define R_RISCV_CALL_PLT 19
#define R_RISCV_GOT_HI20 20
#define R_RISCV_TLS_GOT_HI20 21
#define R_RISCV_TLS_GD_HI20 22
#define R_RISCV_PCREL_HI20 23
#define R_RISCV_PCREL_LO12_I 24
#define R_RISCV_PCREL_LO12_S 25
#define R_RISCV_HI20 26
#define R_RISCV_LO12_I 27
#define R_RISCV_LO12_S 28
#define R_RISCV_TPREL_HI20 29
#define R_RISCV_TPREL_LO12_I 30
#define R_RISCV_TPREL_LO12_S 31
#define R_RISCV_TPREL_ADD 32
#define R_RISCV_ADD8 33
#define R_RISCV_ADD16 34
#define R_RISCV_ADD32 35
#define R_RISCV_ADD64 36
#define R_RISCV_SUB8 37
#define R_RISCV_SUB16 38
#define R_RISCV_SUB32 39
#define R_RISCV_SUB64 40
#define R_RISCV_GNU_VTINHERIT 41
#define R_RISCV_GNU_VTENTRY 42
#define R_RISCV_ALIGN 43
#define R_RISCV_RVC_BRANCH 44
#define R_RISCV_RVC_JUMP 45
#define R_RISCV_RVC_LUI 46
#define R_RISCV_GPREL_I 47
#define R_RISCV_GPREL_S 48
#define R_RISCV_TPREL_I 49
#define R_RISCV_TPREL_S 50
#define R_RISCV_RELAX 51
#define R_RISCV_SUB6 52
#define R_RISCV_SET6 53
#define R_RISCV_SET8 54
#define R_RISCV_SET16 55
#define R_RISCV_SET32 56
#define R_RISCV_32_PCREL 57
#define R_RISCV_NUM 58
#endif /* elf.h */

View File

@ -43,6 +43,7 @@ I386_O = libtcc1.o alloca86.o alloca86-bt.o
X86_64_O = libtcc1.o alloca86_64.o alloca86_64-bt.o
ARM_O = libtcc1.o armeabi.o alloca-arm.o armflush.o
ARM64_O = lib-arm64.o
RISCV64_O =
WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
@ -58,6 +59,7 @@ OBJ-arm-vfp = $(ARM_O) $(DSO_O)
OBJ-arm-eabi = $(ARM_O) $(DSO_O)
OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
OBJ-arm-wince = $(ARM_O) $(WIN_O)
OBJ-riscv64 = $(RISCV64_O) $(DSO_O)
$(BIN) : $(patsubst %.o,$(X)%.o,$(OBJ-$T))
$(XAR) rcs $@ $^

View File

@ -45,25 +45,26 @@ static int nb_states;
#include "i386-gen.c"
#include "i386-link.c"
#include "i386-asm.c"
#endif
#ifdef TCC_TARGET_ARM
#elif defined(TCC_TARGET_ARM)
#include "arm-gen.c"
#include "arm-link.c"
#include "arm-asm.c"
#endif
#ifdef TCC_TARGET_ARM64
#elif defined(TCC_TARGET_ARM64)
#include "arm64-gen.c"
#include "arm64-link.c"
#endif
#ifdef TCC_TARGET_C67
#elif defined(TCC_TARGET_C67)
#include "c67-gen.c"
#include "c67-link.c"
#include "tcccoff.c"
#endif
#ifdef TCC_TARGET_X86_64
#elif defined(TCC_TARGET_X86_64)
#include "x86_64-gen.c"
#include "x86_64-link.c"
#include "i386-asm.c"
#elif defined(TCC_TARGET_RISCV64)
#include "riscv64-gen.c"
#include "riscv64-link.c"
#else
#error unknown target
#endif
#ifdef CONFIG_TCC_ASM
#include "tccasm.c"

193
riscv64-gen.c Normal file
View File

@ -0,0 +1,193 @@
#ifdef TARGET_DEFS_ONLY
// Number of registers available to allocator:
#define NB_REGS 16 // x10-x17 aka a0-a7, f10-f17 aka fa0-fa7
#define TREG_R(x) (x) // x = 0..7
#define TREG_F(x) (x + 10) // x = 0..7
// Register classes sorted from more general to more precise:
#define RC_INT (1 << 0)
#define RC_FLOAT (1 << 1)
#define RC_R(x) (1 << (2 + (x))) // x = 0..7
#define RC_F(x) (1 << (10 + (x))) // x = 0..7
#define RC_IRET (RC_R(0)) // int return register class
#define RC_FRET (RC_F(0)) // float return register class
#define REG_IRET (TREG_R(0)) // int return register number
#define REG_FRET (TREG_F(0)) // float return register number
#define PTR_SIZE 8
#define LDOUBLE_SIZE 16
#define LDOUBLE_ALIGN 16
#define MAX_ALIGN 16
#define CHAR_IS_UNSIGNED
#else
#include "tcc.h"
ST_DATA const int reg_classes[NB_REGS] = {
RC_INT | RC_R(0),
RC_INT | RC_R(1),
RC_INT | RC_R(2),
RC_INT | RC_R(3),
RC_INT | RC_R(4),
RC_INT | RC_R(5),
RC_INT | RC_R(6),
RC_INT | RC_R(7),
RC_FLOAT | RC_F(0),
RC_FLOAT | RC_F(1),
RC_FLOAT | RC_F(2),
RC_FLOAT | RC_F(3),
RC_FLOAT | RC_F(4),
RC_FLOAT | RC_F(5),
RC_FLOAT | RC_F(6),
RC_FLOAT | RC_F(7)
};
// Patch all branches in list pointed to by t to branch to a:
ST_FUNC void gsym_addr(int t_, int a_)
{
uint32_t t = t_;
uint32_t a = a_;
tcc_error("implement me");
while (t) {
unsigned char *ptr = cur_text_section->data + t;
uint32_t next = read32le(ptr);
if (a - t + 0x8000000 >= 0x10000000)
tcc_error("branch out of range");
write32le(ptr, (a - t == 4 ? 0xd503201f : // nop
0x14000000 | ((a - t) >> 2 & 0x3ffffff))); // b
t = next;
}
}
ST_FUNC void load(int r, SValue *sv)
{
tcc_error("implement me");
}
ST_FUNC void store(int r, SValue *sv)
{
tcc_error("implement me");
}
ST_FUNC void gfunc_call(int nb_args)
{
tcc_error("implement me");
}
ST_FUNC void gfunc_prolog(CType *func_type)
{
tcc_error("implement me");
}
ST_FUNC void gen_va_start(void)
{
tcc_error("implement me");
}
ST_FUNC void gen_va_arg(CType *t)
{
tcc_error("implement me");
}
ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
int *align, int *regsize)
{
tcc_error("implement me");
}
ST_FUNC void gfunc_return(CType *func_type)
{
tcc_error("implement me");
}
ST_FUNC void gfunc_epilog(void)
{
tcc_error("implement me");
}
ST_FUNC void gen_fill_nops(int bytes)
{
tcc_error("implement me");
if ((bytes & 3))
tcc_error("alignment of code section not multiple of 4");
}
// Generate forward branch to label:
ST_FUNC int gjmp(int t)
{
tcc_error("implement me");
}
// Generate branch to known address:
ST_FUNC void gjmp_addr(int a)
{
tcc_error("implement me");
}
ST_FUNC int gjmp_cond(int op, int t)
{
tcc_error("implement me");
}
ST_FUNC int gjmp_append(int n, int t)
{
tcc_error("implement me");
}
ST_FUNC int gtst(int inv, int t)
{
tcc_error("implement me");
}
ST_FUNC void gen_opi(int op)
{
tcc_error("implement me");
}
ST_FUNC void gen_opl(int op)
{
tcc_error("implement me");
}
ST_FUNC void gen_opf(int op)
{
tcc_error("implement me");
}
ST_FUNC void gen_cvt_sxtw(void)
{
tcc_error("implement me");
}
ST_FUNC void gen_cvt_itof(int t)
{
tcc_error("implement me");
}
ST_FUNC void gen_cvt_ftoi(int t)
{
tcc_error("implement me");
}
ST_FUNC void gen_cvt_ftof(int t)
{
tcc_error("implement me");
}
ST_FUNC void ggoto(void)
{
tcc_error("implement me");
}
ST_FUNC void gen_vla_sp_save(int addr)
{
tcc_error("implement me");
}
ST_FUNC void gen_vla_sp_restore(int addr)
{
tcc_error("implement me");
}
ST_FUNC void gen_vla_alloc(CType *type, int align)
{
tcc_error("implement me");
}
#endif

122
riscv64-link.c Normal file
View File

@ -0,0 +1,122 @@
#ifdef TARGET_DEFS_ONLY
#define EM_TCC_TARGET EM_RISCV
#define R_DATA_32 R_RISCV_32
#define R_DATA_PTR R_RISCV_64
#define R_JMP_SLOT R_RISCV_JUMP_SLOT
#define R_GLOB_DAT R_RISCV_64
#define R_COPY R_RISCV_COPY
#define R_RELATIVE R_RISCV_RELATIVE
#define R_NUM R_RISCV_NUM
#define ELF_START_ADDR 0x00010000
#define ELF_PAGE_SIZE 0x1000
#define PCRELATIVE_DLLPLT 1
#define RELOCATE_DLLPLT 1
#else /* !TARGET_DEFS_ONLY */
#include "tcc.h"
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
relocations, returns -1. */
int code_reloc (int reloc_type)
{
switch (reloc_type) {
}
tcc_error ("Unknown relocation type: %d", reloc_type);
return -1;
}
/* Returns an enumerator to describe whether and when the relocation needs a
GOT and/or PLT entry to be created. See tcc.h for a description of the
different values. */
int gotplt_entry_type (int reloc_type)
{
switch (reloc_type) {
}
tcc_error ("Unknown relocation type: %d", reloc_type);
return -1;
}
ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
{
Section *plt = s1->plt;
uint8_t *p;
unsigned plt_offset;
if (s1->output_type == TCC_OUTPUT_DLL)
tcc_error("DLLs unimplemented!");
if (plt->data_offset == 0)
section_ptr_add(plt, 32);
plt_offset = plt->data_offset;
p = section_ptr_add(plt, 16);
write64le(p, got_offset);
return plt_offset;
}
/* relocate the PLT: compute addresses and offsets in the PLT now that final
address for PLT and GOT are known (see fill_program_header) */
ST_FUNC void relocate_plt(TCCState *s1)
{
uint8_t *p, *p_end;
if (!s1->plt)
return;
p = s1->plt->data;
p_end = p + s1->plt->data_offset;
if (p < p_end) {
uint64_t plt = s1->plt->sh_addr;
uint64_t got = s1->got->sh_addr;
uint64_t off = (got >> 12) - (plt >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, got=0x%lx, plt=0x%lx)", off, got, plt);
write32le(p, 0x0);
write32le(p + 4, 0x0);
write32le(p + 8, 0x0);
write32le(p + 12, 0x0);
write32le(p + 16, 0x0);
write32le(p + 20, 0x0);
write32le(p + 24, 0x0);
write32le(p + 28, 0x0);
p += 32;
while (p < p_end) {
uint64_t pc = plt + (p - s1->plt->data);
uint64_t addr = got + read64le(p);
uint64_t off = (addr >> 12) - (pc >> 12);
if ((off + ((uint32_t)1 << 20)) >> 21)
tcc_error("Failed relocating PLT (off=0x%lx, addr=0x%lx, pc=0x%lx)", off, addr, pc);
write32le(p, 0x0);
write32le(p + 4, 0x0);
write32le(p + 8, 0x0);
write32le(p + 12, 0x0);
p += 16;
}
}
}
void relocate_init(Section *sr) {}
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
{
int sym_index = ELFW(R_SYM)(rel->r_info);
#ifdef DEBUG_RELOC
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
#endif
switch(type) {
default:
fprintf(stderr, "FIXME: handle reloc type %x at %x [%p] to %x\n",
type, (unsigned)addr, ptr, (unsigned)val);
return;
}
}
#endif

30
tcc.h
View File

@ -139,11 +139,12 @@ extern long double strtold (const char *__nptr, char **__endptr);
/* #define TCC_TARGET_ARM *//* ARMv4 code generator */
/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */
/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */
/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */
/* default target is I386 */
#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
!defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \
!defined(TCC_TARGET_X86_64)
!defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_RISCV64)
# if defined __x86_64__
# define TCC_TARGET_X86_64
# elif defined __arm__
@ -170,6 +171,8 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define TCC_IS_NATIVE
# elif defined __aarch64__ && defined TCC_TARGET_ARM64
# define TCC_IS_NATIVE
# elif defined __riscv && defined __LP64__ && defined TCC_TARGET_RISCV64
# define TCC_IS_NATIVE
# endif
#endif
@ -330,25 +333,26 @@ extern long double strtold (const char *__nptr, char **__endptr);
#ifdef TCC_TARGET_I386
# include "i386-gen.c"
# include "i386-link.c"
#endif
#ifdef TCC_TARGET_X86_64
#elif defined TCC_TARGET_X86_64
# include "x86_64-gen.c"
# include "x86_64-link.c"
#endif
#ifdef TCC_TARGET_ARM
#elif defined TCC_TARGET_ARM
# include "arm-gen.c"
# include "arm-link.c"
# include "arm-asm.c"
#endif
#ifdef TCC_TARGET_ARM64
#elif defined TCC_TARGET_ARM64
# include "arm64-gen.c"
# include "arm64-link.c"
#endif
#ifdef TCC_TARGET_C67
#elif defined TCC_TARGET_C67
# define TCC_TARGET_COFF
# include "coff.h"
# include "c67-gen.c"
# include "c67-link.c"
#elif defined(TCC_TARGET_RISCV64)
# include "riscv64-gen.c"
# include "riscv64-link.c"
#else
#error unknown target
#endif
#undef TARGET_DEFS_ONLY
@ -1594,6 +1598,14 @@ ST_FUNC void gen_va_arg(CType *t);
ST_FUNC void gen_clear_cache(void);
#endif
/* ------------ riscv64-gen.c ------------ */
#ifdef TCC_TARGET_RISCV64
ST_FUNC void gen_cvt_sxtw(void);
ST_FUNC void gen_opl(int op);
ST_FUNC void gfunc_return(CType *func_type);
ST_FUNC void gen_va_start(void);
ST_FUNC void gen_va_arg(CType *t);
#endif
/* ------------ c67-gen.c ------------ */
#ifdef TCC_TARGET_C67
#endif

View File

@ -1548,12 +1548,14 @@ ST_FUNC int gv(int rc)
r = vtop->r & VT_VALMASK;
rc2 = (rc & RC_FLOAT) ? RC_FLOAT : RC_INT;
#ifndef TCC_TARGET_ARM64
#ifndef TCC_TARGET_RISCV64 /* XXX: remove the whole LRET/QRET class */
if (rc == RC_IRET)
rc2 = RC_LRET;
#ifdef TCC_TARGET_X86_64
else if (rc == RC_FRET)
rc2 = RC_QRET;
#endif
#endif
#endif
/* need to reload if:
- constant
@ -2552,7 +2554,7 @@ redo:
/* generic itof for unsigned long long case */
static void gen_cvt_itof1(int t)
{
#ifdef TCC_TARGET_ARM64
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
gen_cvt_itof(t);
#else
if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
@ -2580,7 +2582,7 @@ static void gen_cvt_itof1(int t)
/* generic ftoi for unsigned long long case */
static void gen_cvt_ftoi1(int t)
{
#ifdef TCC_TARGET_ARM64
#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
gen_cvt_ftoi(t);
#else
int st;
@ -2802,7 +2804,7 @@ static void gen_cast(CType *type)
/* need to convert from 32bit to 64bit */
gv(RC_INT);
if (sbt != (VT_INT | VT_UNSIGNED)) {
#if defined(TCC_TARGET_ARM64)
#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_RISCV64)
gen_cvt_sxtw();
#elif defined(TCC_TARGET_X86_64)
int r = gv(RC_INT);
@ -5469,12 +5471,14 @@ special_math_val:
#endif
} else {
#ifndef TCC_TARGET_ARM64
#ifndef TCC_TARGET_RISCV64
#ifdef TCC_TARGET_X86_64
if ((ret.type.t & VT_BTYPE) == VT_QLONG)
#else
if ((ret.type.t & VT_BTYPE) == VT_LLONG)
#endif
ret.r2 = REG_LRET;
#endif
#endif
ret.r = REG_IRET;
}
@ -6015,6 +6019,7 @@ ST_FUNC int expr_const(void)
/* return from function */
#ifndef TCC_TARGET_ARM64
#ifndef TCC_TARGET_RISCV64
static void gfunc_return(CType *func_type)
{
if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
@ -6079,6 +6084,7 @@ static void gfunc_return(CType *func_type)
vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
}
#endif
#endif
static void check_func_return(void)
{