diff --git a/libs/libc/machine/risc-v/rv64/arch_elf.c b/libs/libc/machine/risc-v/rv64/arch_elf.c index 85a78a0e6f8..247e50b5466 100644 --- a/libs/libc/machine/risc-v/rv64/arch_elf.c +++ b/libs/libc/machine/risc-v/rv64/arch_elf.c @@ -37,7 +37,10 @@ * Pre-processor Definitions ****************************************************************************/ -#define OPCODE_SW 0x23 +#define OPCODE_SW 0x23 +#define OPCODE_LUI 0x37 + +#define RVI_OPCODE_MASK 0x7F /**************************************************************************** * Private Data Types @@ -60,6 +63,8 @@ static struct rname_code_s _rname_table[] = {"PCREL_LO12_I", R_RISCV_PCREL_LO12_I}, {"PCREL_LO12_S", R_RISCV_PCREL_LO12_S}, {"PCREL_HI20", R_RISCV_PCREL_HI20}, + {"HI20", R_RISCV_HI20}, + {"LO12_I", R_RISCV_LO12_I}, {"CALL", R_RISCV_CALL}, {"BRANCH", R_RISCV_BRANCH}, {"RVC_JUMP", R_RISCV_RVC_JUMP}, @@ -373,6 +378,50 @@ int up_relocateadd(FAR const Elf64_Rela *rel, FAR const Elf64_Sym *sym, } break; + case R_RISCV_HI20: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.19 LUI */ + + offset = (long)sym->st_value; + uint32_t insn = _get_val((uint16_t *)addr); + + ASSERT(OPCODE_LUI == (insn & RVI_OPCODE_MASK)); + + long imm_hi; + long imm_lo; + _calc_imm(offset, &imm_hi, &imm_lo); + insn = (insn & 0x00000fff) | (imm_hi << 12); + + _set_val((uint16_t *)addr, insn); + } + break; + + case R_RISCV_LO12_I: + { + binfo("%s at %08lx [%08x] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* ADDI, FLW, LD, ... : I-type */ + + offset = (long)sym->st_value; + uint32_t insn = _get_val((uint16_t *)addr); + + long imm_hi; + long imm_lo; + _calc_imm(offset, &imm_hi, &imm_lo); + insn = (insn & 0x000fffff) | (imm_lo << 20); + + _set_val((uint16_t *)addr, insn); + } + break; + case R_RISCV_RVC_JUMP: { binfo("%s at %08lx [%04x] to sym=%p st_value=%08lx\n",