py/nlrxtensa: Convert from assembler to C file with inline asm.

nlr_jump is a little bit inefficient because it now saves a register to
the stack.
This commit is contained in:
Damien George 2017-02-16 17:23:29 +11:00
parent be3d7f91e5
commit a85755aa22
2 changed files with 103 additions and 119 deletions

View File

@ -1,119 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#if defined(__xtensa__)
/*
calling conventions:
a0 = return address
a1 = stack pointer
a2 = first arg, return value
a3-a7 = rest of args
*/
// the offset of nlr_top within mp_state_ctx_t
#define NLR_TOP_OFFSET (2 * 4)
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
.file "nlr.s"
.text
.literal_position
.literal .LC0, NLR_TOP
.align 4
.global nlr_push
.type nlr_push, @function
nlr_push:
// save regs
s32i.n a0, a2, 8
s32i.n a1, a2, 12
s32i.n a8, a2, 16
s32i.n a9, a2, 20
s32i.n a10, a2, 24
s32i.n a11, a2, 28
s32i.n a12, a2, 32
s32i.n a13, a2, 36
s32i.n a14, a2, 40
s32i.n a15, a2, 44
l32r a3, .LC0
l32i.n a4, a3, 0
s32i.n a2, a3, 0
s32i.n a4, a2, 0
movi.n a2, 0
ret.n
.size nlr_push, .-nlr_push
.literal_position
.literal .LC1, NLR_TOP
.align 4
.global nlr_pop
.type nlr_pop, @function
nlr_pop:
l32r a2, .LC1
l32i.n a3, a2, 0
l32i.n a3, a3, 0
s32i.n a3, a2, 0
ret.n
.size nlr_pop, .-nlr_pop
.literal_position
.literal .LC2, NLR_TOP
.align 4
.global nlr_jump
.type nlr_jump, @function
nlr_jump:
l32r a3, .LC2
l32i.n a3, a3, 0 // a3 = nlr_top
bnez.n a3, .L4
call0 nlr_jump_fail
.L4:
s32i.n a2, a3, 4 // nlr_top->ret_val = val
// restore regs
l32i.n a0, a3, 8
l32i.n a1, a3, 12
l32i.n a8, a3, 16
l32i.n a9, a3, 20
l32i.n a10, a3, 24
l32i.n a11, a3, 28
l32i.n a12, a3, 32
l32i.n a13, a3, 36
l32i.n a14, a3, 40
l32i.n a15, a3, 44
l32i.n a3, a3, 0 // a3 = nlr_top->prev
l32r a2, .LC2
s32i.n a3, a2, 0 // nlr_top = a3
movi.n a2, 1 // return 1
ret.n
.size nlr_jump, .-nlr_jump
#endif // defined(__xtensa__)
#if defined(linux)
.section .note.GNU-stack,"",%progbits
#endif

103
py/nlrxtensa.c Normal file
View File

@ -0,0 +1,103 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mpstate.h"
#include "py/nlr.h"
#if !MICROPY_NLR_SETJMP && defined(__xtensa__)
#undef nlr_push
// Xtensa calling conventions:
// a0 = return address
// a1 = stack pointer
// a2 = first arg, return value
// a3-a7 = rest of args
unsigned int nlr_push(nlr_buf_t *nlr) {
__asm volatile (
"s32i.n a0, a2, 8 \n" // save regs...
"s32i.n a1, a2, 12 \n"
"s32i.n a8, a2, 16 \n"
"s32i.n a9, a2, 20 \n"
"s32i.n a10, a2, 24 \n"
"s32i.n a11, a2, 28 \n"
"s32i.n a12, a2, 32 \n"
"s32i.n a13, a2, 36 \n"
"s32i.n a14, a2, 40 \n"
"s32i.n a15, a2, 44 \n"
"j nlr_push_tail \n" // do the rest in C
);
return 0; // needed to silence compiler warning
}
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
nlr->prev = *top;
*top = nlr;
return 0; // normal return
}
void nlr_pop(void) {
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
*top = (*top)->prev;
}
NORETURN void nlr_jump(void *val) {
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
nlr_buf_t *top = *top_ptr;
if (top == NULL) {
nlr_jump_fail(val);
}
top->ret_val = val;
*top_ptr = top->prev;
__asm volatile (
"mov.n a2, %0 \n" // a2 points to nlr_buf
"l32i.n a0, a2, 8 \n" // restore regs...
"l32i.n a1, a2, 12 \n"
"l32i.n a8, a2, 16 \n"
"l32i.n a9, a2, 20 \n"
"l32i.n a10, a2, 24 \n"
"l32i.n a11, a2, 28 \n"
"l32i.n a12, a2, 32 \n"
"l32i.n a13, a2, 36 \n"
"l32i.n a14, a2, 40 \n"
"l32i.n a15, a2, 44 \n"
"movi.n a2, 1 \n" // return 1, non-local return
"ret.n \n" // return
: // output operands
: "r"(top) // input operands
: // clobbered registers
);
for (;;); // needed to silence compiler warning
}
#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__)