esp32: emulate byte access for module text
Tested on ESP-EYE.
This commit is contained in:
parent
df44909b30
commit
f4e7845b85
51
arch/xtensa/include/loadstore.h
Normal file
51
arch/xtensa/include/loadstore.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/xtensa/include/loadstore.h
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __ARCH_XTENSA_INCLUDE_LOADSTORE_H
|
||||||
|
#define __ARCH_XTENSA_INCLUDE_LOADSTORE_H
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Inline functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Function Prototypes
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
uint32_t l32i(const uint32_t *p);
|
||||||
|
void s32i(uint32_t *p, uint32_t value);
|
||||||
|
|
||||||
|
#endif /* __ARCH_XTENSA_INCLUDE_LOADSTORE_H */
|
@ -267,7 +267,8 @@ uint32_t *xtensa_irq_dispatch(int irq, uint32_t *regs);
|
|||||||
uint32_t xtensa_enable_cpuint(uint32_t *shadow, uint32_t intmask);
|
uint32_t xtensa_enable_cpuint(uint32_t *shadow, uint32_t intmask);
|
||||||
uint32_t xtensa_disable_cpuint(uint32_t *shadow, uint32_t intmask);
|
uint32_t xtensa_disable_cpuint(uint32_t *shadow, uint32_t intmask);
|
||||||
void xtensa_panic(int xptcode, uint32_t *regs) noreturn_function;
|
void xtensa_panic(int xptcode, uint32_t *regs) noreturn_function;
|
||||||
void xtensa_user(int exccause, uint32_t *regs) noreturn_function;
|
void xtensa_user_panic(int exccause, uint32_t *regs) noreturn_function;
|
||||||
|
uint32_t *xtensa_user(int exccause, uint32_t *regs);
|
||||||
|
|
||||||
/* Software interrupt handler */
|
/* Software interrupt handler */
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ void xtensa_panic(int xptcode, uint32_t *regs)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void xtensa_user(int exccause, uint32_t *regs)
|
void xtensa_user_panic(int exccause, uint32_t *regs)
|
||||||
{
|
{
|
||||||
#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT)
|
#if CONFIG_TASK_NAME_SIZE > 0 && defined(CONFIG_DEBUG_ALERT)
|
||||||
struct tcb_s *rtcb = running_task();
|
struct tcb_s *rtcb = running_task();
|
||||||
|
76
arch/xtensa/src/common/xtensa_loadstore.S
Normal file
76
arch/xtensa/src/common/xtensa_loadstore.S
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/xtensa/src/common/xtensa_loadstore.S
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include "xtensa_abi.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: l32i
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Execute a L32I instruction
|
||||||
|
*
|
||||||
|
* Entry Conditions:
|
||||||
|
* A2 - a pointer
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.global l32i
|
||||||
|
.type l32i, @function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
l32i:
|
||||||
|
ENTRY0
|
||||||
|
|
||||||
|
l32i a2, a2, 0
|
||||||
|
|
||||||
|
RET0
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: s32i
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Execute a S32I instruction
|
||||||
|
*
|
||||||
|
* Entry Conditions:
|
||||||
|
* A2 - a pointer
|
||||||
|
* A3 - a value to store
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
.global s32i
|
||||||
|
.type s32i, @function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
s32i:
|
||||||
|
ENTRY0
|
||||||
|
|
||||||
|
s32i a3, a2, 0
|
||||||
|
|
||||||
|
RET0
|
@ -238,11 +238,30 @@ _xtensa_user_handler:
|
|||||||
rsr a6, EXCCAUSE /* Argument 1 (a6) = EXCCAUSE */
|
rsr a6, EXCCAUSE /* Argument 1 (a6) = EXCCAUSE */
|
||||||
mov a7, sp /* Argument 2 (a7) = pointer to register save area */
|
mov a7, sp /* Argument 2 (a7) = pointer to register save area */
|
||||||
call4 xtensa_user /* Call xtensa_user */
|
call4 xtensa_user /* Call xtensa_user */
|
||||||
|
mov a2, a6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* xtensa_user should not return */
|
/* Restore registers in preparation to return from interrupt */
|
||||||
|
|
||||||
1: j 1b
|
call0 _xtensa_context_restore /* (Preserves a2) */
|
||||||
|
|
||||||
|
/* Restore only level-specific regs (the rest were already restored) */
|
||||||
|
|
||||||
|
l32i a0, a2, (4 * REG_PS) /* Retrieve interruptee's PS */
|
||||||
|
wsr a0, PS
|
||||||
|
l32i a0, a2, (4 * REG_PC) /* Retrieve interruptee's PC */
|
||||||
|
wsr a0, EPC_1
|
||||||
|
l32i a0, a2, (4 * REG_A0) /* Retrieve interruptee's A0 */
|
||||||
|
l32i sp, a2, (4 * REG_A1) /* Remove interrupt stack frame */
|
||||||
|
l32i a2, a2, (4 * REG_A2) /* Retrieve interruptee's A2 */
|
||||||
|
rsync /* Ensure PS and EPC written */
|
||||||
|
|
||||||
|
/* Return from exception. RFE returns from either the UserExceptionVector
|
||||||
|
* or the KernelExceptionVector. RFE sets PS.EXCM back to 0, and then
|
||||||
|
* jumps to the address in EPC[1]. PS.UM and PS.WOE are left unchanged.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rfe
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: _xtensa_syscall_handler
|
* Name: _xtensa_syscall_handler
|
||||||
@ -464,21 +483,21 @@ _xtensa_coproc_handler:
|
|||||||
#endif
|
#endif
|
||||||
wsr a0, PS
|
wsr a0, PS
|
||||||
|
|
||||||
/* Call xtensa_user, passing both the EXCCAUSE and a pointer to the
|
/* Call xtensa_user_panic, passing both the EXCCAUSE and a pointer to the
|
||||||
* beginning of the register save area.
|
* beginning of the register save area.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef __XTENSA_CALL0_ABI__
|
#ifdef __XTENSA_CALL0_ABI__
|
||||||
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
|
rsr a2, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
|
||||||
mov a3, sp /* Argument 2 (a2) = pointer to register save area */
|
mov a3, sp /* Argument 2 (a2) = pointer to register save area */
|
||||||
calx0 xtensa_user /* Call xtensa_user */
|
calx0 xtensa_user_panic /* Call xtensa_user_panic */
|
||||||
#else
|
#else
|
||||||
rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
|
rsr a6, EXCCAUSE /* Argument 1 (a2) = EXCCAUSE */
|
||||||
mov a7, sp /* Argument 2 (a2) = pointer to register save area */
|
mov a7, sp /* Argument 2 (a2) = pointer to register save area */
|
||||||
call4 xtensa_user /* Call xtensa_user */
|
call4 xtensa_user_panic /* Call xtensa_user_panic */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* xtensa_user should not return */
|
/* xtensa_user_panic should not return */
|
||||||
|
|
||||||
1: j 1b
|
1: j 1b
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ CHIP_ASRCS =
|
|||||||
CHIP_CSRCS = esp32_allocateheap.c esp32_clockconfig.c esp32_cpuint.c
|
CHIP_CSRCS = esp32_allocateheap.c esp32_clockconfig.c esp32_cpuint.c
|
||||||
CHIP_CSRCS += esp32_gpio.c esp32_intdecode.c esp32_irq.c esp32_region.c
|
CHIP_CSRCS += esp32_gpio.c esp32_intdecode.c esp32_irq.c esp32_region.c
|
||||||
CHIP_CSRCS += esp32_timerisr.c
|
CHIP_CSRCS += esp32_timerisr.c
|
||||||
|
CHIP_CSRCS += esp32_user.c
|
||||||
|
|
||||||
# Configuration-dependent ESP32 files
|
# Configuration-dependent ESP32 files
|
||||||
|
|
||||||
@ -109,4 +110,5 @@ endif
|
|||||||
|
|
||||||
ifeq ($(CONFIG_ARCH_USE_MODULE_TEXT),y)
|
ifeq ($(CONFIG_ARCH_USE_MODULE_TEXT),y)
|
||||||
CHIP_CSRCS += esp32_modtext.c
|
CHIP_CSRCS += esp32_modtext.c
|
||||||
|
CMN_ASRCS += xtensa_loadstore.S
|
||||||
endif
|
endif
|
||||||
|
302
arch/xtensa/src/esp32/esp32_user.c
Normal file
302
arch/xtensa/src/esp32/esp32_user.c
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* arch/xtensa/src/esp32/esp32_user.c
|
||||||
|
*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership. The
|
||||||
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the
|
||||||
|
* License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/arch.h>
|
||||||
|
|
||||||
|
#include <arch/loadstore.h>
|
||||||
|
#include <arch/xtensa/core.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include "xtensa.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_USE_MODULE_TEXT
|
||||||
|
extern uint32_t _smodtext;
|
||||||
|
extern uint32_t _emodtext;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_USE_MODULE_TEXT
|
||||||
|
#ifdef CONFIG_ENDIAN_BIG
|
||||||
|
#error not implemented
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_BUILD_PROTECTED) || defined (CONFIG_BUILD_KERNEL)
|
||||||
|
#error permission check not implemented
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: load_uint8
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Fetch a byte using 32-bit aligned access.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static uint8_t load_uint8(const uint8_t *p)
|
||||||
|
{
|
||||||
|
const uint32_t *aligned;
|
||||||
|
uint32_t value;
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
aligned = (const uint32_t *)(((uintptr_t)p) & ~3);
|
||||||
|
value = l32i(aligned);
|
||||||
|
offset = ((uintptr_t)p) & 3;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return value & 0xff;
|
||||||
|
case 1:
|
||||||
|
return (value >> 8) & 0xff;
|
||||||
|
case 2:
|
||||||
|
return (value >> 16) & 0xff;
|
||||||
|
case 3:
|
||||||
|
return (value >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not reached */
|
||||||
|
|
||||||
|
PANIC();
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: store_uint8
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Store a byte using 32-bit aligned access.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void store_uint8(uint8_t *p, uint8_t v)
|
||||||
|
{
|
||||||
|
uint32_t *aligned;
|
||||||
|
uint32_t value;
|
||||||
|
unsigned int offset;
|
||||||
|
|
||||||
|
aligned = (uint32_t *)(((uintptr_t)p) & ~3);
|
||||||
|
value = l32i(aligned);
|
||||||
|
offset = ((uintptr_t)p) & 3;
|
||||||
|
switch (offset)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
value = (value & 0xffffff00) | v;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = (value & 0xffff00ff) | (v << 8);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = (value & 0xff00ffff) | (v << 16);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = (value & 0x00ffffff) | (v << 24);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32i(aligned, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: decode_s8i
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Decode S8I instruction using 32-bit aligned access.
|
||||||
|
* Return non-zero on successful decoding.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int decode_s8i(const uint8_t *p, uint8_t *imm8, uint8_t *s,
|
||||||
|
uint8_t *t)
|
||||||
|
{
|
||||||
|
/* 23 16 15 12 11 8 7 4 3 0
|
||||||
|
* | imm8 |0 1 0 0| s | t |0 0 1 0|
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t b0 = load_uint8(p);
|
||||||
|
uint8_t b1 = load_uint8(p + 1);
|
||||||
|
|
||||||
|
if ((b0 & 0xf) == 2 && (b1 & 0xf0) == 0x40)
|
||||||
|
{
|
||||||
|
*t = b0 >> 4;
|
||||||
|
*s = b1 & 0xf;
|
||||||
|
*imm8 = load_uint8(p + 2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: decode_l8ui
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Decode L8UI instruction using 32-bit aligned access.
|
||||||
|
* Return non-zero on successful decoding.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int decode_l8ui(const uint8_t *p, uint8_t *imm8, uint8_t *s,
|
||||||
|
uint8_t *t)
|
||||||
|
{
|
||||||
|
/* 23 16 15 12 11 8 7 4 3 0
|
||||||
|
* | imm8 |0 0 0 0| s | t |0 0 1 0|
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint8_t b0 = load_uint8(p);
|
||||||
|
uint8_t b1 = load_uint8(p + 1);
|
||||||
|
|
||||||
|
if ((b0 & 0xf) == 2 && (b1 & 0xf0) == 0)
|
||||||
|
{
|
||||||
|
*t = b0 >> 4;
|
||||||
|
*s = b1 & 0xf;
|
||||||
|
*imm8 = load_uint8(p + 2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: advance_pc
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Advance PC register by the given value.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void advance_pc(uint32_t *regs, int diff)
|
||||||
|
{
|
||||||
|
uint32_t nextpc;
|
||||||
|
|
||||||
|
/* Advance to the next instruction. */
|
||||||
|
|
||||||
|
nextpc = regs[REG_PC] + diff;
|
||||||
|
#ifdef XCHAL_HAVE_LOOPS
|
||||||
|
/* See Xtensa ISA 4.3.2.4 Loopback Semantics */
|
||||||
|
|
||||||
|
if (regs[REG_LCOUNT] != 0 && nextpc == regs[REG_LEND])
|
||||||
|
{
|
||||||
|
regs[REG_LCOUNT]--;
|
||||||
|
nextpc = regs[REG_LBEG];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
regs[REG_PC] = nextpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: xtensa_user
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* ESP32-specific user exception handler.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
uint32_t *xtensa_user(int exccause, uint32_t *regs)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_ARCH_USE_MODULE_TEXT
|
||||||
|
/* Emulate byte access for module text.
|
||||||
|
*
|
||||||
|
* ESP32 only allows word-aligned accesses to the instruction memory
|
||||||
|
* regions. A non-aligned access raises a LoadStoreErrorCause exception.
|
||||||
|
* We catch those exception and emulate byte access here because it's
|
||||||
|
* necessary in a few places during dynamic code loading:
|
||||||
|
*
|
||||||
|
* - memcpy as a part of read(2) when loading code from a file system.
|
||||||
|
* - relocation needs to inspect and modify text.
|
||||||
|
*
|
||||||
|
* (thus binfo() is used below)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (exccause == XCHAL_EXCCAUSE_LOAD_STORE_ERROR &&
|
||||||
|
(uintptr_t)&_smodtext <= regs[REG_EXCVADDR] &&
|
||||||
|
(uintptr_t)&_emodtext > regs[REG_EXCVADDR])
|
||||||
|
{
|
||||||
|
uint8_t *pc = (uint8_t *)regs[REG_PC];
|
||||||
|
uint8_t imm8;
|
||||||
|
uint8_t s;
|
||||||
|
uint8_t t;
|
||||||
|
|
||||||
|
binfo("XCHAL_EXCCAUSE_LOAD_STORE_ERROR at %p, pc=%p\n",
|
||||||
|
(FAR void *)regs[REG_EXCVADDR],
|
||||||
|
pc);
|
||||||
|
|
||||||
|
if (decode_s8i(pc, &imm8, &s, &t))
|
||||||
|
{
|
||||||
|
binfo("Emulating S8I imm8=%u, s=%u (%p), t=%u (%p)\n",
|
||||||
|
(unsigned int)imm8,
|
||||||
|
(unsigned int)s,
|
||||||
|
(void *)regs[REG_A0 + s],
|
||||||
|
(unsigned int)t,
|
||||||
|
(void *)regs[REG_A0 + t]);
|
||||||
|
|
||||||
|
DEBUGASSERT(regs[REG_A0 + s] + imm8 == regs[REG_EXCVADDR]);
|
||||||
|
store_uint8(((uint8_t *)regs[REG_A0 + s]) + imm8,
|
||||||
|
regs[REG_A0 + t]);
|
||||||
|
advance_pc(regs, 3);
|
||||||
|
return regs;
|
||||||
|
}
|
||||||
|
else if (decode_l8ui(pc, &imm8, &s, &t))
|
||||||
|
{
|
||||||
|
binfo("Emulating L8UI imm8=%u, s=%u (%p), t=%u (%p)\n",
|
||||||
|
(unsigned int)imm8,
|
||||||
|
(unsigned int)s,
|
||||||
|
(void *)regs[REG_A0 + s],
|
||||||
|
(unsigned int)t,
|
||||||
|
(void *)regs[REG_A0 + t]);
|
||||||
|
|
||||||
|
DEBUGASSERT(regs[REG_A0 + s] + imm8 == regs[REG_EXCVADDR]);
|
||||||
|
regs[REG_A0 + t] = load_uint8(((uint8_t *)regs[REG_A0 + s]) +
|
||||||
|
imm8);
|
||||||
|
advance_pc(regs, 3);
|
||||||
|
return regs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/* xtensa_user_panic never returns. */
|
||||||
|
|
||||||
|
xtensa_user_panic(exccause, regs);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user