diff --git a/boards/risc-v/bl602/bl602evb/configs/elf/defconfig b/boards/risc-v/bl602/bl602evb/configs/elf/defconfig new file mode 100644 index 0000000000..e55f7bcaac --- /dev/null +++ b/boards/risc-v/bl602/bl602evb/configs/elf/defconfig @@ -0,0 +1,83 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_DISABLEBG is not set +# CONFIG_NSH_DISABLE_LOSMART is not set +# CONFIG_NSH_DISABLE_UNAME is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="bl602evb" +CONFIG_ARCH_BOARD_BL602EVB=y +CONFIG_ARCH_CHIP="bl602" +CONFIG_ARCH_CHIP_BL602=y +CONFIG_ARCH_INTERRUPTSTACK=8192 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BL602_HAVE_UART0=y +CONFIG_BL602_TIMER0=y +CONFIG_BOARD_LOOPSPERMSEC=10000 +CONFIG_BUILTIN=y +CONFIG_DEBUG_FEATURES=y +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_SYMBOLS=y +CONFIG_DEFAULT_SMALL=y +CONFIG_DEV_ZERO=y +CONFIG_DISABLE_MQUEUE=y +CONFIG_ELF=y +CONFIG_EXAMPLES_ELF=y +CONFIG_EXAMPLES_HELLO=y +CONFIG_EXAMPLES_HELLO_STACKSIZE=8192 +CONFIG_EXAMPLES_TIMER=y +CONFIG_EXECFUNCS_HAVE_SYMTAB=y +CONFIG_EXECFUNCS_SYSTEM_SYMTAB=y +CONFIG_FS_PROCFS=y +CONFIG_FS_ROMFS=y +CONFIG_IDLETHREAD_STACKSIZE=8192 +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_MAX_TASKS=8 +CONFIG_NFILE_DESCRIPTORS=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_DISABLE_CD=y +CONFIG_NSH_DISABLE_CP=y +CONFIG_NSH_DISABLE_IFUPDOWN=y +CONFIG_NSH_DISABLE_MKDIR=y +CONFIG_NSH_DISABLE_RM=y +CONFIG_NSH_DISABLE_RMDIR=y +CONFIG_NSH_DISABLE_UMOUNT=y +CONFIG_NSH_FILEIOSIZE=64 +CONFIG_NSH_FILE_APPS=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_PTHREAD_STACK_DEFAULT=8192 +CONFIG_RAM_SIZE=134217728 +CONFIG_RAM_START=0xc0800000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_RV32IM_CUSTOM_IRQ_SUPPORT=y +CONFIG_SCHED_WAITPID=y +CONFIG_STACK_COLORATION=y +CONFIG_START_DAY=20 +CONFIG_START_MONTH=3 +CONFIG_START_YEAR=2020 +CONFIG_STDIO_DISABLE_BUFFERING=y +CONFIG_SYMTAB_ORDEREDBYNAME=y +CONFIG_SYSTEM_NSH=y +CONFIG_TASK_NAME_SIZE=12 +CONFIG_TASK_SPAWN_DEFAULT_STACKSIZE=8192 +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_TESTING_OSTEST_FPUSIZE=132 +CONFIG_TIMER=y +CONFIG_TIMER_ARCH=y +CONFIG_UART0_BAUD=2000000 +CONFIG_UART0_RXBUFSIZE=128 +CONFIG_UART0_SERIAL_CONSOLE=y +CONFIG_UART0_TXBUFSIZE=128 +CONFIG_USERMAIN_STACKSIZE=8192 +CONFIG_USER_ENTRYPOINT="nsh_main" diff --git a/boards/risc-v/bl602/bl602evb/scripts/Make.defs b/boards/risc-v/bl602/bl602evb/scripts/Make.defs index 822d09a2e8..af2eb0e907 100644 --- a/boards/risc-v/bl602/bl602evb/scripts/Make.defs +++ b/boards/risc-v/bl602/bl602evb/scripts/Make.defs @@ -64,5 +64,17 @@ NXFLATLDFLAGS1 = -r -d -warn-common NXFLATLDFLAGS2 = $(NXFLATLDFLAGS1) -T$(TOPDIR)/binfmt/libnxflat/gnu-nxflat-pcrel.ld -no-check-sections LDNXFLATFLAGS = -e main -s 2048 +# ELF module definitions + +CELFFLAGS = $(CFLAGS) -fno-common +CXXELFFLAGS = $(CXXFLAGS) -fno-common + +LDELFFLAGS = -melf32lriscv -r -e main +ifeq ($(CONFIG_CYGWIN_WINTOOL),y) + LDELFFLAGS += -T "${shell cygpath -w $(BOARD_DIR)$(DELIM)scripts$(DELIM)gnu-elf.ld}" +else + LDELFFLAGS += -T $(BOARD_DIR)$(DELIM)scripts$(DELIM)gnu-elf.ld +endif + LDFLAGS += --gc-sections -melf32lriscv diff --git a/boards/risc-v/bl602/bl602evb/scripts/gnu-elf.ld b/boards/risc-v/bl602/bl602evb/scripts/gnu-elf.ld new file mode 100644 index 0000000000..8e24692df2 --- /dev/null +++ b/boards/risc-v/bl602/bl602evb/scripts/gnu-elf.ld @@ -0,0 +1,115 @@ +/**************************************************************************** + * boards/risc-v/k210/maix-bit/scripts/gnu-elf.ld + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +SECTIONS +{ + .text 0x00000000 : + { + _stext = . ; + *(.text) + *(.text.*) + *(.gnu.warning) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.jcr) + + /* C++ support: The .init and .fini sections contain specific logic + * to manage static constructors and destructors. + */ + + *(.gnu.linkonce.t.*) + *(.init) /* Old ABI */ + *(.fini) /* Old ABI */ + _etext = . ; + } + + .rodata : + { + _srodata = . ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + _erodata = . ; + } + + .data : + { + _sdata = . ; + *(.data) + *(.data1) + *(.data.*) + *(.gnu.linkonce.d*) + . = ALIGN(4); + _edata = . ; + } + + /* C++ support. For each global and static local C++ object, + * GCC creates a small subroutine to construct the object. Pointers + * to these routines (not the routines themselves) are stored as + * simple, linear arrays in the .ctors section of the object file. + * Similarly, pointers to global/static destructor routines are + * stored in .dtors. + */ + + .ctors : + { + _sctors = . ; + *(.ctors) /* Old ABI: Unallocated */ + *(.init_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .dtors : + { + _sdtors = . ; + *(.dtors) /* Old ABI: Unallocated */ + *(.fini_array) /* New ABI: Allocated */ + _edtors = . ; + } + + .bss : + { + _sbss = . ; + *(.bss) + *(.bss.*) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.b*) + *(COMMON) + _ebss = . ; + } + + /* Stabs debugging sections. */ + + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_info 0 : { *(.debug_info) } + .debug_line 0 : { *(.debug_line) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } +} diff --git a/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c b/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c index cbbb3a3b2c..5194853725 100644 --- a/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c +++ b/boards/risc-v/bl602/bl602evb/src/bl602_bringup.c @@ -45,6 +45,17 @@ #include #endif +#ifdef CONFIG_FS_ROMFS +#include + +#define BL602_XIP_START_ADDR (0x23000000) +#define BL602_XIP_OFFSET (*(volatile uint32_t *)0x4000B434) +#define BL602_ROMFS_FLASH_ADDR (0x1C0000) +#define BL602_ROMFS_XIP_ADDR (BL602_XIP_START_ADDR \ + + BL602_ROMFS_FLASH_ADDR \ + - BL602_XIP_OFFSET) +#endif /* CONFIG_FS_ROMFS */ + #include "chip.h" /**************************************************************************** @@ -201,5 +212,31 @@ int bl602_bringup(void) #endif /* CONFIG_FS_LITTLEFS */ #endif /* CONFIG_BL602_SPIFLASH */ +#ifdef CONFIG_FS_ROMFS + /* Create a ROM disk for the /sbin filesystem */ + + ret = romdisk_register(0, BL602_ROMFS_XIP_ADDR, + 512, + 512); + if (ret < 0) + { + _err("ERROR: romdisk_register failed: %d\n", -ret); + } + else + { + /* Mount the file system */ + + ret = mount("/dev/ram0", + "/sbin", + "romfs", MS_RDONLY, NULL); + if (ret < 0) + { + _err("ERROR: mount(%s,%s,romfs) failed: %d\n", + "dev/ram0", + "/sbin", errno); + } + } +#endif /* CONFIG_FS_ROMFS */ + return ret; } diff --git a/libs/libc/machine/risc-v/rv32/Make.defs b/libs/libc/machine/risc-v/rv32/Make.defs index 45b49d02bd..543aed9f33 100644 --- a/libs/libc/machine/risc-v/rv32/Make.defs +++ b/libs/libc/machine/risc-v/rv32/Make.defs @@ -19,11 +19,13 @@ ############################################################################ ifeq ($(CONFIG_RISCV_MEMCPY),y) - ASRCS += arch_memcpy.S +endif + +ifeq ($(CONFIG_LIBC_ARCH_ELF),y) +CSRCS += arch_elf.c +endif DEPPATH += --dep-path machine/risc-v/rv32 VPATH += :machine/risc-v/rv32 -endif - diff --git a/libs/libc/machine/risc-v/rv32/arch_elf.c b/libs/libc/machine/risc-v/rv32/arch_elf.c new file mode 100644 index 0000000000..7492800dad --- /dev/null +++ b/libs/libc/machine/risc-v/rv32/arch_elf.c @@ -0,0 +1,510 @@ +/**************************************************************************** + * libs/libc/machine/risc-v/rv32/arch_elf.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define OPCODE_SW 0x23 +#define OPCODE_LUI 0x37 + +#define RVI_OPCODE_MASK 0x7F + +/**************************************************************************** + * Private Data Types + ****************************************************************************/ + +struct rname_code_s +{ + const char *name; + int type; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static struct rname_code_s _rname_table[] = +{ + {"RELAX", R_RISCV_RELAX}, + {"RISCV_32", R_RISCV_32}, + {"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}, + {"LO12_S", R_RISCV_LO12_S}, + {"CALL", R_RISCV_CALL}, + {"CALL_PLT", R_RISCV_CALL_PLT}, + {"BRANCH", R_RISCV_BRANCH}, + {"RVC_JUMP", R_RISCV_RVC_JUMP}, + {"RVC_BRANCH", R_RISCV_RVC_BRANCH}, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static const char *_get_rname(int type) +{ + int i = 0; + + for (i = 0; i < sizeof(_rname_table) / sizeof(struct rname_code_s); i++) + { + if (_rname_table[i].type == type) + { + return _rname_table[i].name; + } + } + + /* Not found in the table */ + + return "?????"; +} + +/**************************************************************************** + * Name: _get_val, set_val, _add_val + * + * Description: + * These functions are used when relocating an instruction because we can + * not assume the instruction is word-aligned. + * + ****************************************************************************/ + +static uint32_t _get_val(uint16_t *addr) +{ + uint32_t ret; + ret = *addr | (*(addr + 1)) << 16; + return ret; +} + +static void _set_val(uint16_t *addr, uint32_t val) +{ + *addr = (val & 0xffff); + *(addr + 1) = (val >> 16); + + /* NOTE: Ensure relocation before execution */ + + asm volatile ("fence.i"); +} + +static void _add_val(uint16_t *addr, uint32_t val) +{ + uint32_t cur = _get_val(addr); + _set_val(addr, cur + val); +} + +/**************************************************************************** + * Name: _calc_imm + * + * Description: + * Given offset and obtain imm_hi (20bit) and imm_lo (12bit) + * + * Input Parameters: + * offset - signed 32bit + * imm_hi - signed 20bit + * imm_lo - signed 12bit + * + * Returned Value: + * none + * + ****************************************************************************/ + +static void _calc_imm(long offset, long *imm_hi, long *imm_lo) +{ + long lo; + long hi = offset / 4096; + long r = offset % 4096; + + if (2047 < r) + { + hi++; + } + else if (r < -2048) + { + hi--; + } + + lo = offset - (hi * 4096); + + binfo("offset=%ld: hi=%ld lo=%ld \n", + offset, hi, lo); + + ASSERT(-2048 <= lo && lo <= 2047); + + *imm_lo = lo; + *imm_hi = hi; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_checkarch + * + * Description: + * Given the ELF header in 'hdr', verify that the ELF file is appropriate + * for the current, configured architecture. Every architecture that uses + * the ELF loader must provide this function. + * + * Input Parameters: + * hdr - The ELF header read from the ELF file. + * + * Returned Value: + * True if the architecture supports this ELF file. + * + ****************************************************************************/ + +bool up_checkarch(FAR const Elf_Ehdr *ehdr) +{ + /* Make sure it's an RISCV executable */ + + if (ehdr->e_machine != EM_RISCV) + { + berr("ERROR: Not for RISCV: e_machine=%04x\n", ehdr->e_machine); + return false; + } + + /* Make sure that 32-bit objects are supported */ + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) + { + berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n", + ehdr->e_ident[EI_CLASS]); + return false; + } + + /* Verify endian-ness */ + +#ifdef CONFIG_ENDIAN_BIG + if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB) +#else + if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) +#endif + { + berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n", + ehdr->e_ident[EI_DATA]); + return false; + } + + /* Make sure the entry point address is properly aligned */ + + if ((ehdr->e_entry & 1) != 0) + { + berr("ERROR: Entry point is not properly aligned: %08" PRIx32 "\n", + ehdr->e_entry); + } + + /* TODO: Check ABI here. */ + + return true; +} + +/**************************************************************************** + * Name: up_relocate and up_relocateadd + * + * Description: + * Perform on architecture-specific ELF relocation. Every architecture + * that uses the ELF loader must provide this function. + * + * Input Parameters: + * rel - The relocation type + * sym - The ELF symbol structure containing the fully resolved value. + * There are a few relocation types for a few architectures that do + * not require symbol information. For those, this value will be + * NULL. Implementations of these functions must be able to handle + * that case. + * addr - The address that requires the relocation. + * + * Returned Value: + * Zero (OK) if the relocation was successful. Otherwise, a negated errno + * value indicating the cause of the relocation failure. + * + ****************************************************************************/ + +int up_relocate(FAR const Elf_Rel *rel, FAR const Elf_Sym *sym, + uintptr_t addr) +{ + berr("Not implemented\n"); + return -ENOSYS; +} + +int up_relocateadd(FAR const Elf_Rela *rel, FAR const Elf_Sym *sym, + uintptr_t addr) +{ + long offset; + unsigned int relotype; + + /* All relocations depend upon having valid symbol information */ + + relotype = ELF32_R_TYPE(rel->r_info); + + if (relotype == R_RISCV_RELAX) + { + /* NOTE: RELAX has no symbol, so just return */ + + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] \n", + _get_rname(relotype), + addr, _get_val((uint16_t *)addr)); + + return OK; + } + + if (sym == NULL && relotype != R_RISCV_NONE) + { + return -EINVAL; + } + + /* Do relocation based on relocation type */ + + switch (relotype) + { + case R_RISCV_32: + { + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08" PRIx32 "\n", + _get_rname(relotype), + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); + + _set_val((uint16_t *)addr, + (uint32_t)(sym->st_value + rel->r_addend)); + } + break; + + case R_RISCV_PCREL_LO12_I: + case R_RISCV_PCREL_LO12_S: + { + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08" PRIx32 "\n", + _get_rname(relotype), + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); + + /* NOTE: imm value for mv has been adjusted in previous HI20 */ + } + break; + + case R_RISCV_PCREL_HI20: + case R_RISCV_CALL: + case R_RISCV_CALL_PLT: + { + binfo("%s at %08" PRIxPTR " [%08" PRIx32 "] " + "to sym=%p st_value=%08" PRIx32 "\n", + _get_rname(relotype), + addr, _get_val((uint16_t *)addr), + sym, sym->st_value); + + offset = (long)sym->st_value - (long)addr; + + long imm_hi; + long imm_lo; + + _calc_imm(offset, &imm_hi, &imm_lo); + + /* Adjust auipc (add upper immediate to pc) : 20bit */ + + _add_val((uint16_t *)addr, (imm_hi << 12)); + + if ((_get_val((uint16_t *)(addr + 4)) & 0x7f) == OPCODE_SW) + { + /* Adjust imm for SW : S-type */ + + uint32_t val = + (((int32_t)imm_lo >> 5) << 25) + + (((int32_t)imm_lo & 0x1f) << 7); + + binfo("imm_lo=%ld (%lx), val=%lx \n", imm_lo, imm_lo, val); + + _add_val((uint16_t *)(addr + 4), val); + } + else + { + /* Adjust imm for MV(ADDI)/JALR : I-type */ + + _add_val((uint16_t *)(addr + 4), ((int32_t)imm_lo << 20)); + } + } + break; + + case R_RISCV_BRANCH: + { + binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.23 Conditinal Branches : B type (imm=12bit) */ + + offset = (long)sym->st_value - (long)addr; + uint32_t val = _get_val((uint16_t *)addr) & 0xfe000f80; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for Bx=%ld (0x%lx) (val=0x%08lx) already set! \n", + offset, offset, val); + } + break; + + case R_RISCV_HI20: + { + binfo("%s at %08lx [%08lx] 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 [%08lx] 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_LO12_S: + { + binfo("%s at %08lx [%08lx] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* SW : S-type. + * not merge with R_RISCV_HI20 since the compiler + * may not generates these two instructions continuously. + */ + + offset = (long)sym->st_value; + + long imm_hi; + long imm_lo; + _calc_imm(offset, &imm_hi, &imm_lo); + + uint32_t val = + (((int32_t)imm_lo >> 5) << 25) + + (((int32_t)imm_lo & 0x1f) << 7); + + binfo("imm_lo=%ld (%lx), val=%lx \n", imm_lo, imm_lo, val); + + _add_val((uint16_t *)addr, val); + } + break; + + case R_RISCV_RVC_JUMP: + { + binfo("%s at %08lx [%04lx] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.111 Table 16.6 : Instruction listings for RVC */ + + offset = ((long)sym->st_value - (long)addr); + ASSERT(-2048 <= offset && offset <= 2047); + + uint16_t val = (*(uint16_t *)addr) & 0x1ffc; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for C.J=%ld (0x%lx) (val=0x%04x) already set! \n", + offset, offset, val); + } + break; + + case R_RISCV_RVC_BRANCH: + { + binfo("%s at %08lx [%04lx] to sym=%p st_value=%08lx\n", + _get_rname(relotype), + (long)addr, _get_val((uint16_t *)addr), + sym, (long)sym->st_value); + + /* P.111 Table 16.6 : Instruction listings for RVC */ + + offset = ((long)sym->st_value - (long)addr); + ASSERT(-256 <= offset && offset <= 255); + + uint16_t val = (*(uint16_t *)addr) & 0x1c7c; + + /* NOTE: we assume that a compiler adds an immediate value */ + + ASSERT(offset && val); + + binfo("offset for C.Bx=%ld (0x%lx) (val=0x%04x) already set!\n", + offset, offset, val); + } + break; + + default: + berr("ERROR: Unsupported relocation: %" PRId32 "\n", + ELF32_R_TYPE(rel->r_info)); + ASSERT(false); + return -EINVAL; + } + + return OK; +}