mirror of
https://github.com/micropython/micropython.git
synced 2026-01-06 12:10:13 +01:00
py/emitinlinextensa: Add the rest of LX3 opcodes to the assembler.
This commit expands the Xtensa inline assembler to support most if not all opcodes available on the ESP8266 and LX3 Xtensa cores. This is meant as a stepping stone to add inline assembler support for the ESP32 and its LX6 core, along to windowed-specific opcodes and additional opcodes that are present only on the LX7 core (ESP32-S3 and later). New opcodes being added are covered by tests, and the provided tests were expanded to also include opcodes available in the existing implementation. Given that the ESP8266 space requirements are tighter than ESP32's, certain opcodes that won't be commonly used have been put behind a define to save some space in the general use case. Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
This commit is contained in:
committed by
Damien George
parent
555f1cf488
commit
1006ed69f0
@@ -37,8 +37,10 @@
|
||||
#define WORD_SIZE (4)
|
||||
#define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80))
|
||||
#define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800))
|
||||
#define SIGNED_FIT18(x) ((((x) & 0xfffe0000) == 0) || (((x) & 0xfffe0000) == 0xfffe0000))
|
||||
|
||||
#define ET_OUT_OF_RANGE MP_ERROR_TEXT("ERROR: xtensa %q out of range")
|
||||
#define ET_NOT_ALIGNED MP_ERROR_TEXT("ERROR: %q %q not word-aligned")
|
||||
|
||||
void asm_xtensa_end_pass(asm_xtensa_t *as) {
|
||||
as->num_const = as->cur_const;
|
||||
@@ -266,4 +268,47 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) {
|
||||
asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8);
|
||||
}
|
||||
|
||||
void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition) {
|
||||
uint32_t dest = get_label_dest(as, label);
|
||||
int32_t rel = dest - as->base.code_offset - 4;
|
||||
if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bit_branch);
|
||||
}
|
||||
asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, condition | ((bit >> 4) & 0x01), reg, bit & 0x0F, rel & 0xFF));
|
||||
}
|
||||
|
||||
void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label) {
|
||||
uint32_t dest = get_label_dest(as, label);
|
||||
int32_t rel = dest - as->base.code_offset - 3;
|
||||
if (as->base.pass == MP_ASM_PASS_EMIT) {
|
||||
if ((dest & 0x03) != 0) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_target);
|
||||
}
|
||||
if ((rel & 0x03) != 0) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_location);
|
||||
}
|
||||
if (!SIGNED_FIT18(rel)) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_call0);
|
||||
}
|
||||
}
|
||||
asm_xtensa_op_call0(as, rel);
|
||||
}
|
||||
|
||||
void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label) {
|
||||
uint32_t dest = get_label_dest(as, label);
|
||||
int32_t rel = dest - as->base.code_offset;
|
||||
if (as->base.pass == MP_ASM_PASS_EMIT) {
|
||||
if ((dest & 0x03) != 0) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_target);
|
||||
}
|
||||
if ((rel & 0x03) != 0) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_location);
|
||||
}
|
||||
if (!SIGNED_FIT18(rel) || (rel >= 0)) {
|
||||
mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_l32r);
|
||||
}
|
||||
}
|
||||
asm_xtensa_op_l32r(as, reg, as->base.code_offset, dest);
|
||||
}
|
||||
|
||||
#endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN
|
||||
|
||||
Reference in New Issue
Block a user