Add xtensa AOT support and fix build issue of alios (#223)

* Clean compiling warnings of zephyr samples

* Support xtensa AOT and fix build issue of alios
This commit is contained in:
Weining
2020-04-01 18:38:42 +08:00
committed by GitHub
parent c1a0e6d877
commit c6fc12b7b6
20 changed files with 762 additions and 68 deletions

View File

@ -5,10 +5,50 @@
#include "aot_reloc.h"
#define R_XTENSA_32 1 /* Direct 32 bit */
#define R_XTENSA_SLOT0_OP 20 /* PC relative */
/* for soft-float */
void __floatsidf();
void __divdf3();
void __ltdf2();
/* for mul32 */
void __mulsi3();
void __muldi3();
void __modsi3();
void __divdi3();
static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
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),
};
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)
{
@ -40,6 +80,67 @@ 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;
memcpy(addr_aligned1, bytes, 4);
}
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)
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,
@ -48,7 +149,73 @@ apply_relocation(AOTModule *module,
char *error_buf, uint32 error_buf_size)
{
switch (reloc_type) {
/* TODO: implement relocation for xtensa */
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;
*(uint8**)insn_addr
= (uint8*)symbol_addr + initial_addend + 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*)symbol_addr + 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.");
return false;
}
imm16 = (int16)(relative_offset >> 2);
/* write back the imm16 to the l32r instruction */
if (is_little_endian())
put_imm16_to_addr(imm16, &l32r_insn->l.imm16);
else
put_imm16_to_addr(imm16, &l32r_insn->b.imm16);
break;
}
default:
if (error_buf != NULL)