mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
xtensa: fix semihosting arguments potentially begin optimized out
The compiler was not informed that the assembly block should be treated as a memory barrier and could optimize out the initialization of local arrays which could be used as semihosting arguments. This resulted in garbage values being passed as semihosting call arguments. Additionally this commit changes the approach for placing values into specific register. Instead of clobbers, local register variables are used. This results in simpler generated code, since the compiler is able to place values directly into the registers used for semihosting arguments, avoiding additional moves.
This commit is contained in:
parent
09f5c1d32e
commit
aeed91b589
@ -27,28 +27,32 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
static inline long semihosting_call(long id, long *data, int *out_errno) // NOLINT(readability-non-const-parameter)
|
static inline long semihosting_call(long id, long *data, int *out_errno) // NOLINT(readability-non-const-parameter)
|
||||||
{
|
{
|
||||||
long host_ret;
|
/* GCC doesn't allow using specific register names in constraints for Xtensa.
|
||||||
long host_errno;
|
* For this case, GCC extended inline assembly manual says the following:
|
||||||
|
* If you must use a specific register, but your Machine Constraints do not provide
|
||||||
|
* sufficient control to select the specific register you want, local register variables
|
||||||
|
* may provide a solution.
|
||||||
|
* Using local register variables results in simpler generated code than
|
||||||
|
* the previous implementation which listed a2-a6 as clobbered registers.
|
||||||
|
*/
|
||||||
|
register long a2 asm ("a2") = id;
|
||||||
|
register long a3 asm ("a3") = (long) data[0];
|
||||||
|
register long a4 asm ("a4") = (long) data[1];
|
||||||
|
register long a5 asm ("a5") = (long) data[2];
|
||||||
|
register long a6 asm ("a6") = (long) data[3];
|
||||||
|
|
||||||
/* The break instruction operands should be (1, 14) according to the ISA manual.
|
/* The break instruction operands should be (1, 14) according to the ISA manual.
|
||||||
* We keep (1, 1) for compatibility, until OpenOCD is updated to support both
|
* We keep (1, 1) for compatibility, until OpenOCD is updated to support both
|
||||||
* conventions.
|
* conventions.
|
||||||
*/
|
*/
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"mov a2, %[sys_nr]\n" \
|
"break 1, 1\n"
|
||||||
"mov a3, %[arg1]\n" \
|
: "+r"(a2), "+r"(a3)
|
||||||
"mov a4, %[arg2]\n" \
|
: "r"(a4), "r"(a5), "r"(a6)
|
||||||
"mov a5, %[arg3]\n" \
|
: "memory");
|
||||||
"mov a6, %[arg4]\n" \
|
|
||||||
"break 1, 1\n" \
|
long host_ret = a2;
|
||||||
"mov %[host_ret], a2\n" \
|
long host_errno = a3;
|
||||||
"mov %[host_errno], a3\n" \
|
|
||||||
:[host_ret]"=r"(host_ret), [host_errno]"=r"(host_errno)
|
|
||||||
:[sys_nr]"r"(id),
|
|
||||||
[arg1]"r"(data[0]),
|
|
||||||
[arg2]"r"(data[1]),
|
|
||||||
[arg3]"r"(data[2]),
|
|
||||||
[arg4]"r"(data[3])
|
|
||||||
:"a2", "a3", "a4", "a5", "a6");
|
|
||||||
if (host_ret < 0) {
|
if (host_ret < 0) {
|
||||||
*out_errno = host_errno;
|
*out_errno = host_errno;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user