riscv: GOT loads, signed remainder, ELF flags
* support loading sym addresses from GOT: important for weak syms, fixes 104_inline. This is still incomplete, it only works for taking the sym address, not for directly loading/storing into such symbols (i.e. not for VT_LVAL) * another op: '%' * ELF flags: add EF_RISCV_FLOAT_ABI_DOUBLE, which is our ABI.
This commit is contained in:
parent
b0329ac081
commit
31ecaa7c28
3 changed files with 28 additions and 11 deletions
|
@ -189,12 +189,22 @@ ST_FUNC void load(int r, SValue *sv)
|
||||||
tcc_error("unimp: load(non-local lval)");
|
tcc_error("unimp: load(non-local lval)");
|
||||||
}
|
}
|
||||||
} else if (v == VT_CONST) {
|
} else if (v == VT_CONST) {
|
||||||
int rb = 0, do32bit = 8;
|
int rb = 0, do32bit = 8, doload = 0;
|
||||||
assert(!is_float(sv->type.t) && is_ireg(r));
|
assert(!is_float(sv->type.t) && is_ireg(r));
|
||||||
if (fr & VT_SYM) {
|
if (fr & VT_SYM) {
|
||||||
static Sym label;
|
static Sym label;
|
||||||
|
if (sv->sym->type.t & VT_STATIC) { // XXX do this per linker relax
|
||||||
greloca(cur_text_section, sv->sym, ind,
|
greloca(cur_text_section, sv->sym, ind,
|
||||||
R_RISCV_PCREL_HI20, sv->c.i);
|
R_RISCV_PCREL_HI20, sv->c.i);
|
||||||
|
fc = 0;
|
||||||
|
sv->c.i = 0;
|
||||||
|
} else {
|
||||||
|
if (((unsigned)fc + (1 << 11)) >> 12)
|
||||||
|
tcc_error("unimp: large addend for global address");
|
||||||
|
greloca(cur_text_section, sv->sym, ind,
|
||||||
|
R_RISCV_GOT_HI20, 0);
|
||||||
|
doload = 1;
|
||||||
|
}
|
||||||
if (!label.v) {
|
if (!label.v) {
|
||||||
label.v = tok_alloc(".L0 ", 4)->tok;
|
label.v = tok_alloc(".L0 ", 4)->tok;
|
||||||
label.type.t = VT_VOID | VT_STATIC;
|
label.type.t = VT_VOID | VT_STATIC;
|
||||||
|
@ -205,8 +215,6 @@ ST_FUNC void load(int r, SValue *sv)
|
||||||
greloca(cur_text_section, &label, ind,
|
greloca(cur_text_section, &label, ind,
|
||||||
R_RISCV_PCREL_LO12_I, 0);
|
R_RISCV_PCREL_LO12_I, 0);
|
||||||
rb = rr;
|
rb = rr;
|
||||||
fc = 0;
|
|
||||||
sv->c.i = 0;
|
|
||||||
do32bit = 0;
|
do32bit = 0;
|
||||||
}
|
}
|
||||||
if (is_float(sv->type.t))
|
if (is_float(sv->type.t))
|
||||||
|
@ -244,6 +252,11 @@ ST_FUNC void load(int r, SValue *sv)
|
||||||
}
|
}
|
||||||
if (((unsigned)fc + (1 << 11)) >> 12)
|
if (((unsigned)fc + (1 << 11)) >> 12)
|
||||||
o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc)
|
o(0x37 | (rr << 7) | ((0x800 + fc) & 0xfffff000)), rb = rr; //lui RR, upper(fc)
|
||||||
|
if (doload) {
|
||||||
|
EI(0x03, 3, rr, rr, 0); // ld RR, 0(RR)
|
||||||
|
if (fc)
|
||||||
|
EI(0x13 | do32bit, 0, rr, rr, fc << 20 >> 20); // addi[w] R, x0|R, FC
|
||||||
|
} else
|
||||||
EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC
|
EI(0x13 | do32bit, 0, rr, rb, fc << 20 >> 20); // addi[w] R, x0|R, FC
|
||||||
} else if (v == VT_LOCAL) {
|
} else if (v == VT_LOCAL) {
|
||||||
assert(is_ireg(r));
|
assert(is_ireg(r));
|
||||||
|
@ -636,7 +649,6 @@ static void gen_opil(int op, int ll)
|
||||||
d = ireg(d);
|
d = ireg(d);
|
||||||
ll = ll ? 0 : 8;
|
ll = ll ? 0 : 8;
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case '%':
|
|
||||||
case TOK_PDIV:
|
case TOK_PDIV:
|
||||||
default:
|
default:
|
||||||
tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL));
|
tcc_error("implement me: %s(%s)", __FUNCTION__, get_tok_str(op, NULL));
|
||||||
|
@ -671,6 +683,9 @@ static void gen_opil(int op, int ll)
|
||||||
case '|':
|
case '|':
|
||||||
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b
|
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (6 << 12)); // or d, a, b
|
||||||
break;
|
break;
|
||||||
|
case '%':
|
||||||
|
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (6 << 12)); //rem d, a, b
|
||||||
|
break;
|
||||||
case TOK_UMOD:
|
case TOK_UMOD:
|
||||||
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (7 << 12)); //remu d, a, b
|
o(0x33 | (d << 7) | (a << 15) | (b << 20) | (0x01 << 25) | (7 << 12)); //remu d, a, b
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#else /* !TARGET_DEFS_ONLY */
|
#else /* !TARGET_DEFS_ONLY */
|
||||||
|
|
||||||
|
//#define DEBUG_RELOC
|
||||||
#include "tcc.h"
|
#include "tcc.h"
|
||||||
|
|
||||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||||
|
@ -177,9 +178,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
uint64_t off64;
|
uint64_t off64;
|
||||||
uint32_t off32;
|
uint32_t off32;
|
||||||
int sym_index = ELFW(R_SYM)(rel->r_info);
|
int sym_index = ELFW(R_SYM)(rel->r_info);
|
||||||
#ifdef DEBUG_RELOC
|
|
||||||
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||||
#endif
|
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case R_RISCV_ALIGN:
|
case R_RISCV_ALIGN:
|
||||||
|
@ -223,8 +222,9 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr,
|
||||||
#endif
|
#endif
|
||||||
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
off64 = (int64_t)(val - addr + 0x800) >> 12;
|
||||||
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
if ((off64 + ((uint64_t)1 << 20)) >> 21)
|
||||||
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx",
|
tcc_error("R_RISCV_PCREL_HI20 relocation failed: off=%lx cond=%lx sym=%s",
|
||||||
off64, ((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21));
|
off64, ((int64_t)(off64 + ((uint64_t)1 << 20)) >> 21),
|
||||||
|
symtab_section->link->data + sym->st_name);
|
||||||
write32le(ptr, (read32le(ptr) & 0xfff)
|
write32le(ptr, (read32le(ptr) & 0xfff)
|
||||||
| ((off64 & 0xfffff) << 12));
|
| ((off64 & 0xfffff) << 12));
|
||||||
last_hi.addr = addr;
|
last_hi.addr = addr;
|
||||||
|
|
2
tccelf.c
2
tccelf.c
|
@ -1910,6 +1910,8 @@ static void tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
|
||||||
#else
|
#else
|
||||||
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
|
ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined TCC_TARGET_RISCV64
|
||||||
|
ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
|
||||||
#endif
|
#endif
|
||||||
switch(file_type) {
|
switch(file_type) {
|
||||||
default:
|
default:
|
||||||
|
|
Loading…
Reference in a new issue