summaryrefslogtreecommitdiffstats
path: root/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c
diff options
context:
space:
mode:
Diffstat (limited to 'fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c')
-rw-r--r--fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c
new file mode 100644
index 000000000..3327c396f
--- /dev/null
+++ b/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/aot/arch/aot_reloc_xtensa.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_reloc.h"
+
+#define R_XTENSA_32 1 /* Direct 32 bit */
+#define R_XTENSA_SLOT0_OP 20 /* PC relative */
+
+/* clang-format off */
+/* for soft-float */
+void __floatsidf();
+void __divdf3();
+void __ltdf2();
+
+/* for mul32 */
+void __mulsi3();
+void __muldi3();
+
+void __modsi3();
+
+void __divdi3();
+
+void __udivdi3();
+void __unorddf2();
+void __adddf3();
+void __eqdf2();
+void __muldf3();
+void __gedf2();
+void __ledf2();
+void __fixunsdfsi();
+void __floatunsidf();
+void __subdf3();
+void __nedf2();
+void __fixdfsi();
+void __moddi3();
+void __extendsfdf2();
+void __truncdfsf2();
+void __gtdf2();
+void __umoddi3();
+void __floatdidf();
+void __divsf3();
+void __fixdfdi();
+void __floatundidf();
+
+
+static SymbolMap target_sym_map[] = {
+ REG_COMMON_SYMBOLS
+
+ /* API's for soft-float */
+ /* TODO: only register these symbols when Floating-Point Coprocessor
+ * Option is not enabled */
+ REG_SYM(__floatsidf),
+ REG_SYM(__divdf3),
+ REG_SYM(__ltdf2),
+
+ /* API's for 32-bit integer multiply */
+ /* TODO: only register these symbols when 32-bit Integer Multiply Option
+ * is not enabled */
+ REG_SYM(__mulsi3),
+ REG_SYM(__muldi3),
+
+ REG_SYM(__modsi3),
+ REG_SYM(__divdi3),
+
+ REG_SYM(__udivdi3),
+ REG_SYM(__unorddf2),
+ REG_SYM(__adddf3),
+ REG_SYM(__eqdf2),
+ REG_SYM(__muldf3),
+ REG_SYM(__gedf2),
+ REG_SYM(__ledf2),
+ REG_SYM(__fixunsdfsi),
+ REG_SYM(__floatunsidf),
+ REG_SYM(__subdf3),
+ REG_SYM(__nedf2),
+ REG_SYM(__fixdfsi),
+ REG_SYM(__moddi3),
+ REG_SYM(__extendsfdf2),
+ REG_SYM(__truncdfsf2),
+ REG_SYM(__gtdf2),
+ REG_SYM(__umoddi3),
+ REG_SYM(__floatdidf),
+ REG_SYM(__divsf3),
+ REG_SYM(__fixdfdi),
+ REG_SYM(__floatundidf),
+};
+/* clang-format on */
+
+static void
+set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
+{
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size, "%s", string);
+}
+
+SymbolMap *
+get_target_symbol_map(uint32 *sym_num)
+{
+ *sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
+ return target_sym_map;
+}
+
+void
+get_current_target(char *target_buf, uint32 target_buf_size)
+{
+ snprintf(target_buf, target_buf_size, "xtensa");
+}
+
+static uint32
+get_plt_item_size()
+{
+ return 0;
+}
+
+void
+init_plt_table(uint8 *plt)
+{
+ (void)plt;
+}
+
+uint32
+get_plt_table_size()
+{
+ return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+}
+
+static bool
+check_reloc_offset(uint32 target_section_size, uint64 reloc_offset,
+ uint32 reloc_data_size, char *error_buf,
+ uint32 error_buf_size)
+{
+ if (!(reloc_offset < (uint64)target_section_size
+ && reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: invalid relocation offset.");
+ return false;
+ }
+ return true;
+}
+
+/*
+ * CPU like esp32 can read and write data through the instruction bus, but only
+ * in a word aligned manner; non-word-aligned access will cause a CPU exception.
+ * This function uses a world aligned manner to write 16bit value to instruction
+ * addreess.
+ */
+static void
+put_imm16_to_addr(int16 imm16, int16 *addr)
+{
+ int8 bytes[8];
+ int32 *addr_aligned1, *addr_aligned2;
+
+ addr_aligned1 = (int32 *)((intptr_t)addr & ~3);
+
+ if ((intptr_t)addr % 4 != 3) {
+ *(int32 *)bytes = *addr_aligned1;
+ *(int16 *)(bytes + ((intptr_t)addr % 4)) = imm16;
+ *addr_aligned1 = *(int32 *)bytes;
+ }
+ else {
+ addr_aligned2 = (int32 *)(((intptr_t)addr + 3) & ~3);
+ *(int32 *)bytes = *addr_aligned1;
+ *(int32 *)(bytes + 4) = *addr_aligned2;
+ *(int16 *)(bytes + 3) = imm16;
+ memcpy(addr_aligned1, bytes, 8);
+ }
+}
+
+static union {
+ int a;
+ char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+#if !defined(__packed)
+/*
+ * Note: This version check is a bit relaxed.
+ * The __packed__ attribute has been there since gcc 2 era.
+ */
+#if __GNUC__ >= 3
+#define __packed __attribute__((__packed__))
+#endif
+#endif
+
+typedef union {
+ struct l32r_le {
+ int8 other;
+ int16 imm16;
+ } __packed l;
+
+ struct l32r_be {
+ int16 imm16;
+ int8 other;
+ } __packed b;
+} l32r_insn_t;
+
+bool
+apply_relocation(AOTModule *module, uint8 *target_section_addr,
+ uint32 target_section_size, uint64 reloc_offset,
+ int64 reloc_addend, uint32 reloc_type, void *symbol_addr,
+ int32 symbol_index, char *error_buf, uint32 error_buf_size)
+{
+ switch (reloc_type) {
+ case R_XTENSA_32:
+ {
+ uint8 *insn_addr = target_section_addr + reloc_offset;
+ int32 initial_addend;
+ /* (S + A) */
+ if ((intptr_t)insn_addr & 3) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "instruction address unaligned.");
+ return false;
+ }
+ CHECK_RELOC_OFFSET(4);
+ initial_addend = *(int32 *)insn_addr;
+ *(uintptr_t *)insn_addr = (uintptr_t)symbol_addr + initial_addend
+ + (intptr_t)reloc_addend;
+ break;
+ }
+
+ case R_XTENSA_SLOT0_OP:
+ {
+ uint8 *insn_addr = target_section_addr + reloc_offset;
+ /* Currently only l32r instruction generates R_XTENSA_SLOT0_OP
+ * relocation */
+ l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr;
+ uint8 *reloc_addr;
+ int32 relative_offset /*, initial_addend */;
+ int16 imm16;
+
+ CHECK_RELOC_OFFSET(3); /* size of l32r instruction */
+
+ /*
+ imm16 = is_little_endian() ?
+ l32r_insn->l.imm16 : l32r_insn->b.imm16;
+ initial_addend = (int32)imm16 << 2;
+ */
+
+ reloc_addr =
+ (uint8 *)((uintptr_t)symbol_addr + (intptr_t)reloc_addend);
+
+ if ((intptr_t)reloc_addr & 3) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "relocation address unaligned.");
+ return false;
+ }
+
+ relative_offset =
+ (int32)((intptr_t)reloc_addr
+ - (((intptr_t)insn_addr + 3) & ~(intptr_t)3));
+ /* relative_offset += initial_addend; */
+
+ /* check relative offset boundary */
+ if (relative_offset < -256 * BH_KB || relative_offset > -4) {
+ set_error_buf(error_buf, error_buf_size,
+ "AOT module load failed: "
+ "target address out of range.\n"
+ "Try using `wamrc --size-level=0` to generate "
+ ".literal island.");
+ return false;
+ }
+
+ imm16 = (int16)(relative_offset >> 2);
+
+ /* write back the imm16 to the l32r instruction */
+
+ /* GCC >= 9 complains if we have a pointer that could be
+ * unaligned. This can happen because the struct is packed.
+ * These pragma are to suppress the warnings because the
+ * function put_imm16_to_addr already handles unaligned
+ * pointers correctly. */
+#if __GNUC__ >= 9
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
+#endif
+ if (is_little_endian())
+ put_imm16_to_addr(imm16, &l32r_insn->l.imm16);
+ else
+ put_imm16_to_addr(imm16, &l32r_insn->b.imm16);
+#if __GNUC__ >= 9
+#pragma GCC diagnostic pop
+#endif
+
+ break;
+ }
+
+ default:
+ if (error_buf != NULL)
+ snprintf(error_buf, error_buf_size,
+ "Load relocation section failed: "
+ "invalid relocation type %d.",
+ (int)reloc_type);
+ return false;
+ }
+
+ return true;
+}