summaryrefslogtreecommitdiff
path: root/py/asmxtensa.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/asmxtensa.c')
-rw-r--r--py/asmxtensa.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/py/asmxtensa.c b/py/asmxtensa.c
index 11b61ad94..0e612bfa7 100644
--- a/py/asmxtensa.c
+++ b/py/asmxtensa.c
@@ -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