#include "lib.h" #include "symbol.h" #include "target.h" #include "machine.h" #include #include #define RISCV_32BIT (1 << 0) #define RISCV_64BIT (1 << 1) #define RISCV_MUL (1 << 2) #define RISCV_DIV (1 << 3) #define RISCV_ATOMIC (1 << 4) #define RISCV_FLOAT (1 << 5) #define RISCV_DOUBLE (1 << 6) #define RISCV_FDIV (1 << 7) #define RISCV_COMP (1 << 8) #define RISCV_EMBD (1 << 9) #define RISCV_FPU (RISCV_FLOAT|RISCV_DOUBLE|RISCV_FDIV) #define RISCV_GENERIC (RISCV_MUL|RISCV_DIV|RISCV_ATOMIC|RISCV_FPU|RISCV_ZICSR|RISCV_ZIFENCEI) #define RISCV_ZICSR (1 << 10) #define RISCV_ZIFENCEI (1 << 11) #define RISCV_ZICBOM (1 << 12) #define RISCV_ZIHINTPAUSE (1 << 13) #define RISCV_VECTOR (1 << 14) static unsigned int riscv_flags; static void parse_march_riscv(const char *arg) { static struct { const char *pattern; unsigned int flags; } basic_sets[] = { { "rv32i", RISCV_32BIT }, { "rv32e", RISCV_32BIT|RISCV_EMBD }, { "rv32g", RISCV_32BIT|RISCV_GENERIC }, { "rv64i", RISCV_64BIT }, { "rv64g", RISCV_64BIT|RISCV_GENERIC }, }, extensions[] = { { "m", RISCV_MUL|RISCV_DIV }, { "a", RISCV_ATOMIC }, { "f", RISCV_FLOAT|RISCV_FDIV|RISCV_ZICSR }, { "d", RISCV_DOUBLE|RISCV_FDIV|RISCV_ZICSR }, { "c", RISCV_COMP }, { "v", RISCV_VECTOR|RISCV_FPU|RISCV_ZICSR }, { "_zicsr", RISCV_ZICSR }, { "_zifencei", RISCV_ZIFENCEI }, { "_zicbom", RISCV_ZICBOM }, { "_zihintpause", RISCV_ZIHINTPAUSE }, }; int i; // Each -march=.. options entirely overrides previous ones riscv_flags = 0; for (i = 0; i < ARRAY_SIZE(basic_sets); i++) { const char *pat = basic_sets[i].pattern; size_t len = strlen(pat); if (!strncmp(arg, pat, len)) { riscv_flags |= basic_sets[i].flags; arg += len; goto ext; } } unknown: fprintf(stderr, "WARNING: invalid argument to '-march': '%s'\n", arg); return; ext: for (i = 0; i < ARRAY_SIZE(extensions); i++) { const char *pat = extensions[i].pattern; size_t len = strlen(pat); if (!strncmp(arg, pat, len)) { riscv_flags |= extensions[i].flags; arg += len; } } if (arg[0]) goto unknown; } static void init_riscv(const struct target *self) { if (arch_cmodel == CMODEL_UNKNOWN) arch_cmodel = CMODEL_MEDLOW; if (fpic) arch_cmodel = CMODEL_PIC; if (riscv_flags == 0) riscv_flags = self->flags; } static void init_riscv32(const struct target *self) { fast16_ctype = &int_ctype; ufast16_ctype = &uint_ctype; fast32_ctype = &int_ctype; ufast32_ctype = &uint_ctype; init_riscv(self); } static void predefine_riscv(const struct target *self) { static const char *cmodels[CMODEL_LAST] = { [CMODEL_MEDANY] = "medany", [CMODEL_MEDLOW] = "medlow", [CMODEL_PIC] = "pic", }; const char *cmodel = cmodels[arch_cmodel]; predefine("__riscv", 1, "1"); predefine("__riscv_xlen", 1, "%d", ptr_ctype.bit_size); if (riscv_flags & RISCV_ATOMIC) predefine("__riscv_atomic", 1, "1"); if (riscv_flags & RISCV_COMP) predefine("__riscv_compressed", 1, "1"); if (riscv_flags & RISCV_DIV) predefine("__riscv_div", 1, "1"); if (riscv_flags & RISCV_EMBD) predefine("__riscv_32e", 1, "1"); if (riscv_flags & RISCV_FPU) predefine("__riscv_flen", 1, "%d", (riscv_flags & RISCV_DOUBLE) ? 64 : 32); if (riscv_flags & RISCV_FDIV) predefine("__riscv_fdiv", 1, "1"); if (riscv_flags & RISCV_FDIV) predefine("__riscv_fsqrt", 1, "1"); if (riscv_flags & RISCV_MUL) predefine("__riscv_mul", 1, "1"); if ((riscv_flags & RISCV_MUL) && (riscv_flags & RISCV_DIV)) predefine("__riscv_muldiv", 1, "1"); if (riscv_flags & RISCV_ZICSR) predefine("__riscv_zicsr", 1, "1"); if (riscv_flags & RISCV_ZIFENCEI) predefine("__riscv_zifencei", 1, "1"); if (riscv_flags & RISCV_ZICBOM) predefine("__riscv_zicbom", 1, "1"); if (riscv_flags & RISCV_ZIHINTPAUSE) predefine("__riscv_zihintpause", 1, "1"); if (riscv_flags & RISCV_VECTOR) { predefine("__riscv_vector", 1, "1"); predefine("__riscv_v_min_vlen", 1, "128"); predefine("__riscv_v_elen", 1, "64"); predefine("__riscv_v_elen_fp", 1, "64"); } if (cmodel) predefine_strong("__riscv_cmodel_%s", cmodel); } const struct target target_riscv32 = { .mach = MACH_RISCV32, .bitness = ARCH_LP32, .big_endian = 0, .unsigned_char = 1, .flags = RISCV_32BIT|RISCV_GENERIC|RISCV_COMP, .target_64bit = &target_riscv64, .init = init_riscv32, .predefine = predefine_riscv, .parse_march = parse_march_riscv, }; const struct target target_riscv64 = { .mach = MACH_RISCV64, .bitness = ARCH_LP64, .big_endian = 0, .unsigned_char = 1, .has_int128 = 1, .flags = RISCV_64BIT|RISCV_GENERIC|RISCV_COMP, .target_32bit = &target_riscv32, .init = init_riscv, .predefine = predefine_riscv, .parse_march = parse_march_riscv, };