Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Lapshin <alexey.lapshin@espressif.com>2023-08-08 23:07:04 +0300
committerJeff Johnston <jjohnstn@redhat.com>2023-08-24 17:52:36 +0300
commit42fc2fa37c5995b642d128705cc67316bf9254b7 (patch)
tree95a31ab40177b41b3416f7cc5239048a27baae56 /libgloss/xtensa
parent90d3b16d2b93d573501394d88538c99335edc343 (diff)
libgloss: add Xtensa port
Supported esp32 and esp32s2 boards: https://github.com/espressif/esp-toolchain-docs/blob/main/gcc/build-and-run-native-app.md
Diffstat (limited to 'libgloss/xtensa')
-rw-r--r--libgloss/xtensa/Makefile.inc55
-rw-r--r--libgloss/xtensa/acinclude.m45
-rw-r--r--libgloss/xtensa/app.elf.ld190
-rw-r--r--libgloss/xtensa/board.elf.specs5
-rw-r--r--libgloss/xtensa/boards/esp32/board.c24
-rw-r--r--libgloss/xtensa/boards/esp32/include/soc/cpu.h16
-rw-r--r--libgloss/xtensa/boards/esp32/include/soc/uart.h24
-rw-r--r--libgloss/xtensa/boards/esp32/memory.elf.ld26
-rw-r--r--libgloss/xtensa/boards/esp32s3/board.c24
-rw-r--r--libgloss/xtensa/boards/esp32s3/include/soc/cpu.h16
-rw-r--r--libgloss/xtensa/boards/esp32s3/include/soc/uart.h24
-rw-r--r--libgloss/xtensa/boards/esp32s3/memory.elf.ld21
-rw-r--r--libgloss/xtensa/crt0.S20
-rw-r--r--libgloss/xtensa/crt1-boards.S223
-rw-r--r--libgloss/xtensa/crt1-sim.S201
-rw-r--r--libgloss/xtensa/default.specs2
-rw-r--r--libgloss/xtensa/include/register_access.h12
-rw-r--r--libgloss/xtensa/include/syscalls.h64
-rw-r--r--libgloss/xtensa/include/xtensa/corebits.h186
-rw-r--r--libgloss/xtensa/nano.specs18
-rw-r--r--libgloss/xtensa/sim-call.S12
-rw-r--r--libgloss/xtensa/sim-vectors.S186
-rw-r--r--libgloss/xtensa/sim.elf.specs5
-rw-r--r--libgloss/xtensa/sleep.S69
-rw-r--r--libgloss/xtensa/sys.openocd.specs8
-rw-r--r--libgloss/xtensa/sys.qemu.specs8
-rw-r--r--libgloss/xtensa/syscalls.c205
-rw-r--r--libgloss/xtensa/window-vectors.S252
28 files changed, 1901 insertions, 0 deletions
diff --git a/libgloss/xtensa/Makefile.inc b/libgloss/xtensa/Makefile.inc
new file mode 100644
index 000000000..02308e4f3
--- /dev/null
+++ b/libgloss/xtensa/Makefile.inc
@@ -0,0 +1,55 @@
+CPPFLAGS += -D_LIBGLOSS -I$(srcdir)/%D%/include
+
+multilibtool_DATA += \
+ %D%/default.specs \
+ %D%/nano.specs \
+ %D%/sim.elf.specs \
+ %D%/board.elf.specs \
+ %D%/sys.qemu.specs \
+ %D%/sys.openocd.specs \
+ %D%/crt0.o
+
+multilibtool_LIBRARIES += %D%/libgloss.a
+
+if HAVE_XTENSA_BOARD_ESP
+multilibtool_DATA += \
+ %D%/app.elf.ld \
+ %D%/crt1-sim.o \
+ %D%/crt1-boards.o
+
+%C%_libgloss_a_SOURCES = \
+ %D%/sleep.S \
+ %D%/syscalls.c \
+ %D%/window-vectors.S
+
+multilibtool_LIBRARIES += %D%/libsys_qemu.a
+%C%_libsys_qemu_a_CPPFLAGS = -DQEMU_SEMIHOSTING
+%C%_libsys_qemu_a_SOURCES = \
+ %D%/sim-vectors.S \
+ %D%/sim-call.S \
+ %D%/syscalls.c
+
+multilibtool_LIBRARIES += %D%/libsys_openocd.a
+%C%_libsys_openocd_a_CPPFLAGS = -DOPENOCD_SEMIHOSTING
+%C%_libsys_openocd_a_SOURCES = \
+ %D%/syscalls.c
+
+if HAVE_XTENSA_BOARD_ESP32
+multilibtool_DATA += %D%/boards/esp32/memory.elf.ld
+%C%_libgloss_a_SOURCES += %D%/boards/esp32/board.c
+%C%_libgloss_a_CPPFLAGS = -I$(srcdir)/%D%/boards/esp32/include
+%C%_libsys_qemu_a_CPPFLAGS += -I$(srcdir)/%D%/boards/esp32/include
+%C%_libsys_openocd_a_CPPFLAGS += -I$(srcdir)/%D%/boards/esp32/include
+endif
+
+if HAVE_XTENSA_BOARD_ESP32S3
+multilibtool_DATA += %D%/boards/esp32s3/memory.elf.ld
+%C%_libgloss_a_SOURCES += %D%/boards/esp32s3/board.c
+%C%_libgloss_a_CPPFLAGS = -I$(srcdir)/%D%/boards/esp32s3/include
+%C%_libsys_qemu_a_CPPFLAGS += -I$(srcdir)/%D%/boards/esp32s3/include
+%C%_libsys_openocd_a_CPPFLAGS += -I$(srcdir)/%D%/boards/esp32s3/include
+endif
+endif
+
+%D%/crt0.$(OBJEXT): %D%/crt0.S
+ $(AM_V_CPPAS)$(CPPASCOMPILE) $(CPPFLAGS) -o $@ -c $<
diff --git a/libgloss/xtensa/acinclude.m4 b/libgloss/xtensa/acinclude.m4
new file mode 100644
index 000000000..fc98f8a3d
--- /dev/null
+++ b/libgloss/xtensa/acinclude.m4
@@ -0,0 +1,5 @@
+XTENSA_BOARD_ESP=`echo $CC | sed 's/.*-mdynconfig=xtensa_\(.*\)\.so.*/\1/;s/.*-mcpu=\(^ *\).*/\1/;s/.* .*/unknown/'`
+AC_SUBST([XTENSA_BOARD_ESP])
+AM_CONDITIONAL([HAVE_XTENSA_BOARD_ESP32], [test x$XTENSA_BOARD_ESP = xesp32])
+AM_CONDITIONAL([HAVE_XTENSA_BOARD_ESP32S3], [test x$XTENSA_BOARD_ESP = xesp32s3])
+AM_CONDITIONAL([HAVE_XTENSA_BOARD_ESP], [echo $XTENSA_BOARD_ESP | grep -w -e esp32 -e esp32s3 >/dev/null 2>&1])
diff --git a/libgloss/xtensa/app.elf.ld b/libgloss/xtensa/app.elf.ld
new file mode 100644
index 000000000..12c7eb8ab
--- /dev/null
+++ b/libgloss/xtensa/app.elf.ld
@@ -0,0 +1,190 @@
+__stack = ORIGIN(dram_seg) + LENGTH(dram_seg);
+__MIN_STACK_SIZE = 0x1000;
+
+ENTRY(_start)
+SECTIONS
+{
+ . = SEGMENT_START("iram_seg", 0);
+ .vectors :
+ {
+ _vector_table = ABSOLUTE(.);
+ . = 0x0;
+ KEEP(*(.WindowVectors.text));
+ . = 0x180;
+ KEEP(*(.Level2InterruptVector.text));
+ . = 0x1c0;
+ KEEP(*(.Level3InterruptVector.text));
+ . = 0x200;
+ KEEP(*(.Level4InterruptVector.text));
+ . = 0x240;
+ KEEP(*(.Level5InterruptVector.text));
+ . = 0x280;
+ KEEP(*(.DebugExceptionVector.text));
+ . = 0x2c0;
+ KEEP(*(.NMIExceptionVector.text));
+ . = 0x300;
+ KEEP(*(.KernelExceptionVector.text));
+ . = 0x340;
+ KEEP(*(.UserExceptionVector.text));
+ . = 0x3C0;
+ KEEP(*(.DoubleExceptionVector.text));
+ . = 0x400;
+ KEEP(*(.ResetVector.text));
+ *(.*Vector.literal)
+ . = ALIGN (16);
+ } > iram_seg
+
+ text :
+ {
+ KEEP (*(.init.literal))
+ KEEP (*(SORT_NONE(.init)))
+ *(.literal .text .stub .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ KEEP (*(.fini.literal))
+ KEEP (*(SORT_NONE(.fini)))
+ } > iram_seg
+
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+
+ .rodata :
+ {
+ *(.rodata .rodata.* .gnu.linkonce.r.*)
+ *(.rodata1)
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*)
+ }
+
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
+ KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
+ KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+
+ _data_start = .;
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ SORT(CONSTRUCTORS)
+ *(.data1)
+ }
+ _edata = .; PROVIDE (edata = .);
+ . = .;
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we do not
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ }
+ . = ALIGN(32 / 8);
+ . = ALIGN(32 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+
+ /* Check if data + heap + stack exceeds RAM limit */
+ ASSERT(. <= __stack - __MIN_STACK_SIZE, "region DRAM overflowed by .data and .bss sections")
+
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* DWARF 3 */
+ .debug_pubtypes 0 : { *(.debug_pubtypes) }
+ .debug_ranges 0 : { *(.debug_ranges) }
+ /* DWARF Extension. */
+ .debug_macro 0 : { *(.debug_macro) }
+ .debug_addr 0 : { *(.debug_addr) }
+ .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
+ /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
+}
+
diff --git a/libgloss/xtensa/board.elf.specs b/libgloss/xtensa/board.elf.specs
new file mode 100644
index 000000000..87cff19e7
--- /dev/null
+++ b/libgloss/xtensa/board.elf.specs
@@ -0,0 +1,5 @@
+*startfile:
+crt1-boards%O%s
+
+*lib:
+-lc --whole-archive -lgloss --no-whole-archive -lpthread_stubs -lc %Tmemory.elf.ld %Tapp.elf.ld
diff --git a/libgloss/xtensa/boards/esp32/board.c b/libgloss/xtensa/boards/esp32/board.c
new file mode 100644
index 000000000..f5c73e533
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32/board.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdint.h>
+#include <soc/uart.h>
+
+void board_init(void)
+{
+ WRITE_REGISTER(UART0_CLKDIV_REG, UART0_CLKDIV_VAL);
+}
+
+void board_uart_write_char(char c)
+{
+ /* wait until txfifo_cnt == 0 */
+ while (UART0_TXFIFO_CNT) {
+ ;
+ }
+ if (c == '\n') {
+ WRITE_REGISTER(UART0_TX_ADDR, '\r');
+ }
+ WRITE_REGISTER(UART0_TX_ADDR, c);
+}
diff --git a/libgloss/xtensa/boards/esp32/include/soc/cpu.h b/libgloss/xtensa/boards/esp32/include/soc/cpu.h
new file mode 100644
index 000000000..4a16fb236
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32/include/soc/cpu.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef SOC_CPU_H
+#define SOC_CPU_H
+
+/*
+ * ESP32 starts with CPU frequency 40MHz
+ * Let's do not reconfigure it to simplify libgloss
+ */
+#define CPU_FREQUENCY_MHZ 40
+#define CPU_FREQUENCY_HZ (CPU_FREQUENCY_MHZ * 1000000)
+
+#endif // SOC_CPU_H
diff --git a/libgloss/xtensa/boards/esp32/include/soc/uart.h b/libgloss/xtensa/boards/esp32/include/soc/uart.h
new file mode 100644
index 000000000..c7b7eb281
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32/include/soc/uart.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef SOC_UART_H
+#define SOC_UART_H
+
+#include <soc/cpu.h>
+#include <register_access.h>
+
+#define UART0_BAUDRATE 115200
+
+#define UART0_TX_ADDR 0x60000000
+#define UART0_BASE 0x3ff40000
+#define UART0_CLKDIV_REG (UART0_BASE + 0x14)
+#define UART0_STATUS (UART0_BASE + 0x1c)
+#define UART0_CLKDIV_VAL (CPU_FREQUENCY_HZ / UART0_BAUDRATE )
+#define UART0_TXFIFO_CNT (((READ_REGISTER(UART0_STATUS)) >> 16) & 0xff)
+
+
+void board_uart_write_char(char c);
+
+#endif // SOC_UART_H
diff --git a/libgloss/xtensa/boards/esp32/memory.elf.ld b/libgloss/xtensa/boards/esp32/memory.elf.ld
new file mode 100644
index 000000000..fa0e423b5
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32/memory.elf.ld
@@ -0,0 +1,26 @@
+/*
+ * IROM/DRAM definition in QEMU:
+ * [ESP32_MEMREGION_IROM] = { 0x40000000, 0x70000 },
+ * [ESP32_MEMREGION_DRAM] = { 0x3ffae000, 0x52000 },
+ *
+ * In theory we could use whole DRAM section, but I had some faults when using
+ * memory in range 0x3ffae000 - 0x3ffb0000
+ *
+ * But used memory range for data such as esp-idf for ESP32 to satisfy user's
+ * expectation on chip emulation
+ *
+ * Pass '--defsym=entire_dram_seg=1' to linker script to use whole DRAM
+ *
+ */
+
+MEMORY
+{
+ iram_seg (X) : org = 0x40078000, len = 0x28000
+/* 64k at the end of DRAM, after ROM bootloader stack
+ * or entire DRAM (for QEMU only)
+ */
+ dram_seg (RW) : org = DEFINED(entire_dram_seg) ? 0x3FFB0000 : 0x3FFF0000,
+ len = DEFINED(entire_dram_seg) ? 0x50000 : 0x10000
+}
+
+
diff --git a/libgloss/xtensa/boards/esp32s3/board.c b/libgloss/xtensa/boards/esp32s3/board.c
new file mode 100644
index 000000000..f5c73e533
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32s3/board.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <stdint.h>
+#include <soc/uart.h>
+
+void board_init(void)
+{
+ WRITE_REGISTER(UART0_CLKDIV_REG, UART0_CLKDIV_VAL);
+}
+
+void board_uart_write_char(char c)
+{
+ /* wait until txfifo_cnt == 0 */
+ while (UART0_TXFIFO_CNT) {
+ ;
+ }
+ if (c == '\n') {
+ WRITE_REGISTER(UART0_TX_ADDR, '\r');
+ }
+ WRITE_REGISTER(UART0_TX_ADDR, c);
+}
diff --git a/libgloss/xtensa/boards/esp32s3/include/soc/cpu.h b/libgloss/xtensa/boards/esp32s3/include/soc/cpu.h
new file mode 100644
index 000000000..2210ba7b0
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32s3/include/soc/cpu.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef SOC_CPU_H
+#define SOC_CPU_H
+
+/*
+ * ESP32S3 starts with CPU frequency 40MHz
+ * Let's do not reconfigure it to simplify libgloss
+ */
+#define CPU_FREQUENCY_MHZ 40
+#define CPU_FREQUENCY_HZ (CPU_FREQUENCY_MHZ * 1000000)
+
+#endif // SOC_CPU_H
diff --git a/libgloss/xtensa/boards/esp32s3/include/soc/uart.h b/libgloss/xtensa/boards/esp32s3/include/soc/uart.h
new file mode 100644
index 000000000..c6241fdec
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32s3/include/soc/uart.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef SOC_UART_H
+#define SOC_UART_H
+
+#include <soc/cpu.h>
+#include <register_access.h>
+
+#define UART0_BAUDRATE 115200
+
+#define UART0_TX_ADDR 0x60000000
+#define UART0_BASE 0x60000000
+#define UART0_CLKDIV_REG (UART0_BASE + 0x14)
+#define UART0_STATUS (UART0_BASE + 0x1c)
+#define UART0_CLKDIV_VAL (CPU_FREQUENCY_HZ / UART0_BAUDRATE )
+#define UART0_TXFIFO_CNT (((READ_REGISTER(UART0_STATUS)) >> 16) & 0x3ff)
+
+
+void board_uart_write_char(char c);
+
+#endif // SOC_UART_H
diff --git a/libgloss/xtensa/boards/esp32s3/memory.elf.ld b/libgloss/xtensa/boards/esp32s3/memory.elf.ld
new file mode 100644
index 000000000..6426b7fc6
--- /dev/null
+++ b/libgloss/xtensa/boards/esp32s3/memory.elf.ld
@@ -0,0 +1,21 @@
+/*
+ * IROM/DRAM definition in QEMU:
+ * [ESP32S3_MEMREGION_IROM] = { 0x40000000, 0x60000 },
+ * [ESP32S3_MEMREGION_DRAM] = { 0x3FC80000, 0x70000 },
+ *
+ * In theory we could use whole DRAM section, but I had some faults when using
+ * memory in range 0x3ffae000 - 0x3ffb0000
+ *
+ * But used memory range for data such as esp-idf for ESP32S3 to satisfy user's
+ * expectation on chip emulation
+ *
+ * Pass '--defsym=entire_dram_seg=1' to linker script to use whole DRAM
+ *
+ */
+
+MEMORY
+{
+ iram_seg (X) : org = 0x40378000, len = 0x70000
+ dram_seg (RW) : org = DEFINED(entire_dram_seg) ? 0x3FC80000 : 0x3FCF0000,
+ len = DEFINED(entire_dram_seg) ? 0x70000 : 0x10000
+}
diff --git a/libgloss/xtensa/crt0.S b/libgloss/xtensa/crt0.S
new file mode 100644
index 000000000..67c359c5b
--- /dev/null
+++ b/libgloss/xtensa/crt0.S
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/* crt0.S
+ * Dummy startup file which calls main() function.
+ * It can be used for compilation tests only.
+ */
+
+ .text
+
+ /*
+ * Simple jump to main().
+ */
+
+ .global _start
+ _start:
+ movi a4, main
+ jx a4 /* jump to main */
diff --git a/libgloss/xtensa/crt1-boards.S b/libgloss/xtensa/crt1-boards.S
new file mode 100644
index 000000000..a703634af
--- /dev/null
+++ b/libgloss/xtensa/crt1-boards.S
@@ -0,0 +1,223 @@
+// crt1-boards.S
+//
+// For most hardware / boards, this code sets up the C calling context
+// (setting up stack, PS, and clearing BSS) and jumps to __clibrary_start
+// which sets up the C library, calls constructors and registers destructors,
+// and calls main().
+//
+// Control arrives here at _start from the reset vector or from crt0-app.S.
+
+// Copyright (c) 1998-2013 Tensilica Inc.
+//
+// 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 <xtensa/corebits.h>
+
+
+// Exports
+.global _start
+
+// Imports
+// __clibrary_init from C library (eg. newlib or uclibc)
+// exit from C library
+// main from user application
+// board_init board-specific (uart/mingloss/tinygloss.c)
+// xthal_dcache_all_writeback from HAL library
+// __stack from linker script (see LSP Ref Manual)
+// __bss_start from linker script (see LSP Ref Manual)
+// _end from linker script (see LSP Ref Manual)
+
+.type main, @function
+
+# define CALL call4
+# define CALLX callx4
+# define ARG1 a6 /* 1st outgoing call argument */
+# define ARG2 a7 /* 2nd outgoing call argument */
+# define ARG3 a8 /* 3rd outgoing call argument */
+# define ARG4 a9 /* 4th outgoing call argument */
+# define ARG5 a10 /* 5th outgoing call argument */
+
+
+/**************************************************************************/
+
+ .text
+ .align 4
+_start:
+ // _start is typically NOT at the beginning of the text segment --
+ // it is always called from either the reset vector or other code
+ // that does equivalent initialization (such as crt0-app.S).
+ //
+ // Assumptions on entry to _start:
+ // - low (level-one) and medium priority interrupts are disabled
+ // via PS.INTLEVEL and/or INTENABLE (PS.INTLEVEL is expected to
+ // be zeroed, to potentially enable them, before calling main)
+ // - C calling context not initialized:
+ // - PS not initialized
+ // - SP not initialized
+ // - the following are initialized:
+ // - LITBASE, cache attributes, WindowBase, WindowStart,
+ // CPENABLE, FP's FCR and FSR, EXCSAVE[n]
+
+ // Keep a0 zero. It is used to initialize a few things.
+ // It is also the return address, where zero indicates
+ // that the frame used by _start is the bottommost frame.
+ //
+
+ movi a0, 0 // keep this register zero.
+
+ wsr a0, INTENABLE // INTENABLE value is not defined after reset.
+ //make sure that interrupts are shut off (*before* we lower PS.INTLEVEL and PS.EXCM!)
+
+ // Windowed register init, so we can call windowed code (eg. C code).
+ movi a1, 1
+ wsr a1, WINDOWSTART
+ // The processor always clears WINDOWBASE at reset, so no need to clear it here.
+ // It resets WINDOWSTART to 1 starting with LX2.0/X7.0 (RB-2006.0).
+ // However, assuming hard reset is not yet always practical, so do this anyway:
+ wsr a0, WINDOWBASE
+ rsync
+
+ // Set VECBASE to use our vectors instead vectors in ROM
+ movi a1, _vector_table
+ wsr a1, VECBASE
+
+ // Initialize the stack pointer.
+ // See the "ABI and Software Conventions" chapter in the
+ // Xtensa ISA Reference manual for details.
+
+ // NOTE: Because the _start routine does not use any memory in its
+ // stack frame, and because all of its CALL instructions use a
+ // window size of 4 (or zero), the stack frame for _start can be empty.
+
+ movi sp, __stack
+
+ /*
+ * Now that sp (a1) is set, we can set PS as per the application
+ * (user vector mode, enable interrupts, enable window exceptions if applicable).
+ */
+ movi a3, PS_UM|PS_WOE
+ wsr a3, PS
+ rsync
+
+
+ /*
+ * Do any initialization that affects the memory map, such as
+ * setting up TLB entries, that needs to be done before we can
+ * successfully clear BSS (e.g. if some BSS segments are in
+ * remapped areas).
+ *
+ * NOTE: This hook works where the reset vector does not unpack
+ * segments (see "ROM packing" in the LSP manual), or where
+ * unpacking of segments is not affected by memory remapping.
+ * If ROM unpacking is affected, TLB setup must be done in
+ * assembler from the reset vector.
+ *
+ * The __memmap_init() routine can be a C function, however it
+ * does not have BSS initialized! In particular, __memmap_init()
+ * cannot set BSS variables, i.e. uninitialized global variables
+ * (they'll be wiped out by the following BSS clear), nor can it
+ * assume they are yet initialized to zero.
+ *
+ * The __memmap_init() function is optional. It is marked as a
+ * weak symbol, so that it gets valued zero if not defined.
+ */
+ .weak __memmap_init
+ movi a4, __memmap_init
+ beqz a4, 1f
+ CALLX a4
+1:
+
+ /*
+ * Clear the BSS (uninitialized data) segments.
+ * This code supports multiple zeroed sections (*.bss).
+ *
+ */
+ movi a6, __bss_start
+ movi a8, _end
+ sub a8, a8, a6
+ movi a7, 0
+ CALL memset
+
+ /* init semihosting if has function */
+ .weak __semihosting_init
+ movi a4, __semihosting_init
+ beqz a4, 2f
+ CALLX a4
+2:
+
+ // We can now call C code, the C calling environment has been initialized.
+ //
+ // From this point on, we use ABI-specific macros to refer to registers a0 .. a15
+ // (ARG#).
+
+
+ .type board_init, @function
+ .type __clibrary_init, @function
+ .type exit, @function
+
+
+ // Initialize the board (eg. UART, etc).
+ CALL board_init
+
+ /*
+ * Call __clibrary_init to initialize the C library:
+ *
+ * void __clibrary_init(int argc, char ** argv, char ** environ,
+ * void(*init_func)(void), void(*fini_func)(void));
+ */
+
+ // Pass an empty argv array, with an empty string as the program name.
+
+ .weak _init
+ .weak _fini
+ movi ARG1, _start_argc // argc address
+ movi ARG2, _start_argv // argv = ["", 0]
+ movi ARG3, _start_envp // envp = [0]
+ movi ARG4, _init // function that calls constructors
+ movi ARG5, _fini // function that calls destructors
+ l32i ARG1, ARG1, 0 // argc = 1
+ CALL __clibrary_init
+
+ // Call: int main(int argc, char ** argv, char ** environ);
+ movi ARG1, _start_argc // argc address
+ movi ARG2, _start_argv // argv = ["", 0]
+ movi ARG3, _start_envp // envp = [0]
+ l32i ARG1, ARG1, 0 // argc = 1
+ CALL main
+ // The return value is the same register as the first outgoing argument.
+ CALL exit // exit with main's return value
+ // Does not return here.
+
+ .data
+ // Mark argc/argv/envp parameters as weak so that an external
+ // object file can override them.
+ .weak _start_argc, _start_argv, _start_envp
+ .align 4
+_start_argv:
+ .word _start_null // empty program name
+_start_null:
+_start_envp:
+ .word 0 // end of argv array, empty string, empty environ
+_start_argc:
+ .word 1 // one argument (program name)
+ .text
+
+ .size _start, . - _start
+
diff --git a/libgloss/xtensa/crt1-sim.S b/libgloss/xtensa/crt1-sim.S
new file mode 100644
index 000000000..4f9924c3b
--- /dev/null
+++ b/libgloss/xtensa/crt1-sim.S
@@ -0,0 +1,201 @@
+// crt1-sim.S
+// For the Xtensa simulator target, this code sets up the C calling context
+// and calls main() (via __clibrary_start).
+// Control arrives here at _start from the reset vector or from crt0-app.S.
+
+// Copyright (c) 1998-2012 Tensilica Inc.
+//
+// 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 <xtensa/config/core-isa.h>
+#include <xtensa/corebits.h>
+#include <syscalls.h>
+
+// Exports
+.global _start
+
+// Imports
+// __clibrary_init from C library (eg. newlib or uclibc)
+// exit from C library
+// main from user application
+// __stack from linker script (see LSP Ref Manual)
+
+.type __clibrary_init, @function
+.type main, @function
+.type exit, @function
+
+# define CALL call4
+# define CALLX callx4
+# define ARG1 a6 /* 1st outgoing call argument */
+# define ARG2 a7 /* 2nd outgoing call argument */
+# define ARG3 a8 /* 3rd outgoing call argument */
+# define ARG4 a9 /* 4th outgoing call argument */
+# define ARG5 a10 /* 5th outgoing call argument */
+
+ .data
+ .weak _start_envp // allow overriding
+ .align 4
+_start_envp: .word 0 // empty environ
+
+ .text
+ .align 4
+
+_start:
+ // _start is typically NOT at the beginning of the text segment --
+ // it is always called from either the reset vector or other code
+ // that does equivalent initialization (such as crt0-app.S).
+ //
+ // Assumptions on entry to _start:
+ // - low (level-one) and medium priority interrupts are disabled
+ // via PS.INTLEVEL and/or INTENABLE (PS.INTLEVEL is expected to
+ // be zeroed, to potentially enable them, before calling main)
+ // - C calling context not initialized:
+ // - PS not initialized
+ // - SP not initialized
+ // - the following are initialized:
+ // - LITBASE, cache attributes, WindowBase, WindowStart,
+ // CPENABLE, FP's FCR and FSR, EXCSAVE[n]
+
+ // Keep a0 zero. It is used to initialize a few things.
+ // It is also the return address, where zero indicates
+ // that the frame used by _start is the bottommost frame.
+ //
+ movi a0, 0 // keep this register zero.
+
+ wsr a0, INTENABLE // INTENABLE value is not defined after reset.
+ //make sure that interrupts are shut off (*before* we lower PS.INTLEVEL and PS.EXCM!)
+
+ // Windowed register init, so we can call windowed code (eg. C code).
+ movi a1, 1
+ wsr a1, WINDOWSTART
+ // The processor always clears WINDOWBASE at reset, so no need to clear it here.
+ // It resets WINDOWSTART to 1 starting with LX2.0/X7.0 (RB-2006.0).
+ // However, assuming hard reset is not yet always practical, so do this anyway:
+ wsr a0, WINDOWBASE
+ rsync
+
+ // Set VECBASE to use our vectors instead vectors in ROM
+ movi a1, _vector_table
+ wsr a1, VECBASE
+
+
+ // Run only one core
+ // Multi-threading could be supported in future
+ rsr.prid a1 // core and multiprocessor ID
+ extui a1, a1, 13, 1 // extract core ID
+ beqz a1, .Lcore0 // goto Lcore0 for core0 only
+.Lsuspend: // other cores are suspended
+ waiti 0
+ j .Lsuspend
+
+.Lcore0:
+ // Initialize the stack pointer.
+ // See the "ABI and Software Conventions" chapter in the
+ // Xtensa ISA Reference manual for details.
+
+ // NOTE: Because the _start routine does not use any memory in its
+ // stack frame, and because all of its CALL instructions use a
+ // window size of 4, the stack frame for _start can be empty.
+ movi sp, __stack
+
+ // reserve stack space for
+ // - argv array
+ // - argument strings
+ movi a2, SYS_argv_size
+ simcall // returns size of argv[] + its strings in a2
+
+ // The stack only needs 16-byte alignment.
+ // However, here we round up the argv size further to 128 byte multiples
+ // so that in most cases, variations in argv[0]'s path do not result in
+ // different stack allocation. Otherwise, such variations can impact
+ // execution timing (eg. due to cache effects etc) for the same code and data.
+ // If we have a PIF, it's more likely the extra required space is okay.
+ addi a2, a2, 127
+ srli a2, a2, 7
+ slli a2, a2, 7
+
+ // No need to use MOVSP because we have no caller (we're the
+ // base caller); in fact it's better not to use MOVSP in this
+ // context, to avoid unnecessary ALLOCA exceptions and copying
+ // from undefined memory:
+ // sub a3, sp, a2
+ // movsp sp, a3
+ sub sp, sp, a2
+
+ /*
+ * Now that sp (a1) is set, we can set PS as per the application
+ * (user vector mode, enable interrupts, enable window exceptions if applicable).
+ */
+ movi a3, PS_UM|PS_WOE // PS.WOE = 1, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0
+ wsr a3, PS
+ rsync
+
+ #if XCHAL_HAVE_FP || XCHAL_HAVE_DFP
+ movi a3, 1
+ wsr a3, CPENABLE
+ #endif
+
+1:
+
+ /*
+ * Clear the BSS (uninitialized data) segments.
+ * This code supports multiple zeroed sections (*.bss).
+ * For speed, we clear memory using an ISS simcall
+ * (see crt1-boards.S for more generic BSS clearing code).
+ */
+ movi a6, __bss_start
+ movi a7, _end
+ bgeu a6, a7, .Lnobss
+.Lbssloop:
+ movi a2, SYS_memset
+ l32i a3, a6, 0 // arg1 = fill start address
+ movi a4, 0 // arg2 = fill pattern
+ l32i a5, a6, 4 // get end address
+ addi a6, a6, 8 // next bss table entry
+ sub a5, a5, a3 // arg3 = fill size in bytes
+ simcall // memset(a3,a4,a5)
+ bltu a6, a7, .Lbssloop // loop until end of bss table
+.Lnobss:
+
+ mov a3, sp // tell simcall where to write argv[]
+ movi a2, SYS_argv
+ simcall // write argv[] array at a3
+
+ movi a2, SYS_argc
+ simcall // put argc in a2
+
+ .weak _init
+ .weak _fini
+ mov ARG2, sp // argv
+ movi ARG3, _start_envp // envp
+ movi ARG4, _init // _init
+ movi ARG5, _fini // _fini
+ CALL __clibrary_init
+
+ mov ARG1, a2 // argc
+ mov ARG2, sp // argv
+ CALL main
+
+ // The return value is the same register as the first outgoing argument.
+ CALL exit // exit with main's return value
+ // Does not return here.
+
+ .size _start, . - _start
+
diff --git a/libgloss/xtensa/default.specs b/libgloss/xtensa/default.specs
new file mode 100644
index 000000000..6002fe450
--- /dev/null
+++ b/libgloss/xtensa/default.specs
@@ -0,0 +1,2 @@
+*lib:
+-lc -lnosys -lc
diff --git a/libgloss/xtensa/include/register_access.h b/libgloss/xtensa/include/register_access.h
new file mode 100644
index 000000000..517220481
--- /dev/null
+++ b/libgloss/xtensa/include/register_access.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef REGISTER_ACCESS_H
+#define REGISTER_ACCESS_H
+
+#define WRITE_REGISTER(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
+#define READ_REGISTER(addr) (*((volatile uint32_t *)(addr)))
+
+#endif // REGISTER_ACCESS_H
diff --git a/libgloss/xtensa/include/syscalls.h b/libgloss/xtensa/include/syscalls.h
new file mode 100644
index 000000000..323d6fa35
--- /dev/null
+++ b/libgloss/xtensa/include/syscalls.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef XTENSA_SIMCALL_H
+#define XTENSA_SIMCALL_H
+
+#ifdef OPENOCD_SEMIHOSTING
+/* This data based on libgloss project (file aarch64/svc.h) */
+
+#define ESP_SEMIHOSTING_SYS_DRV_INFO 0x100
+#define ADP_STOPPED_APPLICATION_EXIT 0x20026
+
+#define SYS_close 0x02
+#define SYS_clock 0x10
+#define SYS_elapsed 0x30
+#define SYS_errno 0x13
+#define SYS_exit 0x18
+#define SYS_exit_extended 0x20
+#define SYS_flen 0x0C
+#define SYS_get_cmdline 0x15
+#define SYS_heapinfo 0x16
+#define SYS_iserror 0x08
+#define SYS_istty 0x09
+#define SYS_open 0x01
+#define SYS_read 0x06
+#define SYS_readc 0x07
+#define SYS_remove 0x0E
+#define SYS_rename 0x0F
+#define SYS_lseek 0x0A
+#define SYS_system 0x12
+#define SYS_tickfreq 0x31
+#define SYS_time 0x11
+#define SYS_tmpnam 0x0D
+#define SYS_write 0x05
+#define SYS_writec 0x03
+#define SYS_write0 0x04
+
+#else
+
+/* This data based on QEMU project (file target/xtensa/xtensa-semi.c) */
+
+#define SYS_exit 1
+#define SYS_read 3
+#define SYS_write 4
+#define SYS_open 5
+#define SYS_close 6
+#define SYS_lseek 19
+#define SYS_select_one 29
+#define SYS_sendto 27
+#define SYS_recvfrom 28
+#define SYS_select_one 29
+#define SYS_bind 30
+#define SYS_ioctl 31
+
+#define SYS_argc 1000
+#define SYS_argv_size 1001
+#define SYS_argv 1002
+#define SYS_memset 1004
+
+#endif /* OPENOCD_SEMIHOSTING */
+
+#endif /* !XTENSA_SIMCALL_H */
diff --git a/libgloss/xtensa/include/xtensa/corebits.h b/libgloss/xtensa/include/xtensa/corebits.h
new file mode 100644
index 000000000..445e33495
--- /dev/null
+++ b/libgloss/xtensa/include/xtensa/corebits.h
@@ -0,0 +1,186 @@
+/*
+ * xtensa/corebits.h - Xtensa Special Register field positions, masks, values.
+ *
+ * (In previous releases, these were defined in specreg.h, a generated file.
+ * This file is not generated, ie. it is processor configuration independent.)
+ */
+
+/* $Id: //depot/rel/Eaglenest/Xtensa/OS/include/xtensa/corebits.h#2 $ */
+
+/*
+ * Copyright (c) 2005-2011 Tensilica Inc.
+ *
+ * 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.
+ */
+
+#ifndef XTENSA_COREBITS_H
+#define XTENSA_COREBITS_H
+
+/* EXCCAUSE register fields: */
+#define EXCCAUSE_EXCCAUSE_SHIFT 0
+#define EXCCAUSE_EXCCAUSE_MASK 0x3F
+/* EXCCAUSE register values: */
+/*
+ * General Exception Causes
+ * (values of EXCCAUSE special register set by general exceptions,
+ * which vector to the user, kernel, or double-exception vectors).
+ */
+#define EXCCAUSE_ILLEGAL 0 /* Illegal Instruction */
+#define EXCCAUSE_SYSCALL 1 /* System Call (SYSCALL instruction) */
+#define EXCCAUSE_INSTR_ERROR 2 /* Instruction Fetch Error */
+# define EXCCAUSE_IFETCHERROR 2 /* (backward compatibility macro, deprecated, avoid) */
+#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error */
+# define EXCCAUSE_LOADSTOREERROR 3 /* (backward compatibility macro, deprecated, avoid) */
+#define EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt */
+# define EXCCAUSE_LEVEL1INTERRUPT 4 /* (backward compatibility macro, deprecated, avoid) */
+#define EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (MOVSP instruction) for alloca */
+#define EXCCAUSE_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero */
+#define EXCCAUSE_SPECULATION 7 /* Use of Failed Speculative Access (not implemented) */
+#define EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction */
+#define EXCCAUSE_UNALIGNED 9 /* Unaligned Load or Store */
+/* Reserved 10..11 */
+#define EXCCAUSE_INSTR_DATA_ERROR 12 /* PIF Data Error on Instruction Fetch (RB-200x and later) */
+#define EXCCAUSE_LOAD_STORE_DATA_ERROR 13 /* PIF Data Error on Load or Store (RB-200x and later) */
+#define EXCCAUSE_INSTR_ADDR_ERROR 14 /* PIF Address Error on Instruction Fetch (RB-200x and later) */
+#define EXCCAUSE_LOAD_STORE_ADDR_ERROR 15 /* PIF Address Error on Load or Store (RB-200x and later) */
+#define EXCCAUSE_ITLB_MISS 16 /* ITLB Miss (no ITLB entry matches, hw refill also missed) */
+#define EXCCAUSE_ITLB_MULTIHIT 17 /* ITLB Multihit (multiple ITLB entries match) */
+#define EXCCAUSE_INSTR_RING 18 /* Ring Privilege Violation on Instruction Fetch */
+/* Reserved 19 */ /* Size Restriction on IFetch (not implemented) */
+#define EXCCAUSE_INSTR_PROHIBITED 20 /* Cache Attribute does not allow Instruction Fetch */
+/* Reserved 21..23 */
+#define EXCCAUSE_DTLB_MISS 24 /* DTLB Miss (no DTLB entry matches, hw refill also missed) */
+#define EXCCAUSE_DTLB_MULTIHIT 25 /* DTLB Multihit (multiple DTLB entries match) */
+#define EXCCAUSE_LOAD_STORE_RING 26 /* Ring Privilege Violation on Load or Store */
+/* Reserved 27 */ /* Size Restriction on Load/Store (not implemented) */
+#define EXCCAUSE_LOAD_PROHIBITED 28 /* Cache Attribute does not allow Load */
+#define EXCCAUSE_STORE_PROHIBITED 29 /* Cache Attribute does not allow Store */
+/* Reserved 30..31 */
+#define EXCCAUSE_CP_DISABLED(n) (32+(n)) /* Access to Coprocessor 'n' when disabled */
+#define EXCCAUSE_CP0_DISABLED 32 /* Access to Coprocessor 0 when disabled */
+#define EXCCAUSE_CP1_DISABLED 33 /* Access to Coprocessor 1 when disabled */
+#define EXCCAUSE_CP2_DISABLED 34 /* Access to Coprocessor 2 when disabled */
+#define EXCCAUSE_CP3_DISABLED 35 /* Access to Coprocessor 3 when disabled */
+#define EXCCAUSE_CP4_DISABLED 36 /* Access to Coprocessor 4 when disabled */
+#define EXCCAUSE_CP5_DISABLED 37 /* Access to Coprocessor 5 when disabled */
+#define EXCCAUSE_CP6_DISABLED 38 /* Access to Coprocessor 6 when disabled */
+#define EXCCAUSE_CP7_DISABLED 39 /* Access to Coprocessor 7 when disabled */
+/* Reserved 40..63 */
+
+/* PS register fields: */
+#define PS_WOE_SHIFT 18
+#define PS_WOE_MASK 0x00040000
+#define PS_WOE PS_WOE_MASK
+#define PS_WOE_ABI PS_WOE_MASK
+#define PS_CALLINC_SHIFT 16
+#define PS_CALLINC_MASK 0x00030000
+#define PS_CALLINC(n) (((n)&3)<<PS_CALLINC_SHIFT) /* n = 0..3 */
+#define PS_OWB_SHIFT 8
+#define PS_OWB_MASK 0x00000F00
+#define PS_OWB(n) (((n)&15)<<PS_OWB_SHIFT) /* n = 0..15 (or 0..7) */
+#define PS_RING_SHIFT 6
+#define PS_RING_MASK 0x000000C0
+#define PS_RING(n) (((n)&3)<<PS_RING_SHIFT) /* n = 0..3 */
+#define PS_UM_SHIFT 5
+#define PS_UM_MASK 0x00000020
+#define PS_UM PS_UM_MASK
+#define PS_EXCM_SHIFT 4
+#define PS_EXCM_MASK 0x00000010
+#define PS_EXCM PS_EXCM_MASK
+#define PS_INTLEVEL_SHIFT 0
+#define PS_INTLEVEL_MASK 0x0000000F
+#define PS_INTLEVEL(n) ((n)&PS_INTLEVEL_MASK) /* n = 0..15 */
+/* Backward compatibility (deprecated): */
+#define PS_PROGSTACK_SHIFT PS_UM_SHIFT
+#define PS_PROGSTACK_MASK PS_UM_MASK
+#define PS_PROG_SHIFT PS_UM_SHIFT
+#define PS_PROG_MASK PS_UM_MASK
+#define PS_PROG PS_UM
+
+/* DBREAKCn register fields: */
+#define DBREAKC_MASK_SHIFT 0
+#define DBREAKC_MASK_MASK 0x0000003F
+#define DBREAKC_LOADBREAK_SHIFT 30
+#define DBREAKC_LOADBREAK_MASK 0x40000000
+#define DBREAKC_STOREBREAK_SHIFT 31
+#define DBREAKC_STOREBREAK_MASK 0x80000000
+
+/* DEBUGCAUSE register fields: */
+#define DEBUGCAUSE_DEBUGINT_SHIFT 5
+#define DEBUGCAUSE_DEBUGINT_MASK 0x20 /* debug interrupt */
+#define DEBUGCAUSE_BREAKN_SHIFT 4
+#define DEBUGCAUSE_BREAKN_MASK 0x10 /* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_SHIFT 3
+#define DEBUGCAUSE_BREAK_MASK 0x08 /* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_SHIFT 2
+#define DEBUGCAUSE_DBREAK_MASK 0x04 /* DBREAK match */
+#define DEBUGCAUSE_IBREAK_SHIFT 1
+#define DEBUGCAUSE_IBREAK_MASK 0x02 /* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_SHIFT 0
+#define DEBUGCAUSE_ICOUNT_MASK 0x01 /* ICOUNT would increment to zero */
+
+/* MESR register fields: */
+#define MESR_MEME 0x00000001 /* memory error */
+#define MESR_MEME_SHIFT 0
+#define MESR_DME 0x00000002 /* double memory error */
+#define MESR_DME_SHIFT 1
+#define MESR_RCE 0x00000010 /* recorded memory error */
+#define MESR_RCE_SHIFT 4
+#define MESR_LCE
+#define MESR_LCE_SHIFT ?
+#define MESR_LCE_L
+#define MESR_ERRENAB 0x00000100
+#define MESR_ERRENAB_SHIFT 8
+#define MESR_ERRTEST 0x00000200
+#define MESR_ERRTEST_SHIFT 9
+#define MESR_DATEXC 0x00000400
+#define MESR_DATEXC_SHIFT 10
+#define MESR_INSEXC 0x00000800
+#define MESR_INSEXC_SHIFT 11
+#define MESR_WAYNUM_SHIFT 16
+#define MESR_ACCTYPE_SHIFT 20
+#define MESR_MEMTYPE_SHIFT 24
+#define MESR_ERRTYPE_SHIFT 30
+
+/* MEMCTL register fields: */
+#define MEMCTL_SNOOP_EN_SHIFT 1
+#define MEMCTL_SNOOP_EN 0x02 /* enable snoop responses (default 0) */
+#define MEMCTL_L0IBUF_EN_SHIFT 0
+#define MEMCTL_L0IBUF_EN 0x01 /* enable loop instr. buffer (default 1) */
+#define MEMCTL_INV_EN_SHIFT 23
+#define MEMCTL_INV_EN 0x00800000 /* invalidate cache ways being increased */
+#define MEMCTL_DCWU_SHIFT 8
+#define MEMCTL_DCWU_BITS 5
+#define MEMCTL_DCWA_SHIFT 13
+#define MEMCTL_DCWA_BITS 5
+#define MEMCTL_ICWU_SHIFT 18
+#define MEMCTL_ICWU_BITS 5
+#define MEMCTL_DCWU_MASK 0x00001F00 /* Bits 8-12 dcache ways in use */
+#define MEMCTL_DCWA_MASK 0x0003E000 /* Bits 13-17 dcache ways allocatable */
+#define MEMCTL_ICWU_MASK 0x007C0000 /* Bits 18-22 icache ways in use */
+#define MEMCTL_DCWU_CLR_MASK ~(MEMCTL_DCWU_MASK)
+#define MEMCTL_DCWA_CLR_MASK ~(MEMCTL_DCWA_MASK)
+#define MEMCTL_ICWU_CLR_MASK ~(MEMCTL_ICWU_MASK)
+#define MEMCTL_DCW_CLR_MASK (MEMCTL_DCWU_CLR_MASK | MEMCTL_DCWA_CLR_MASK)
+#define MEMCTL_IDCW_CLR_MASK (MEMCTL_DCW_CLR_MASK | MEMCTL_ICWU_CLR_MASK)
+
+
+#endif /*XTENSA_COREBITS_H*/
+
diff --git a/libgloss/xtensa/nano.specs b/libgloss/xtensa/nano.specs
new file mode 100644
index 000000000..adf7abbaf
--- /dev/null
+++ b/libgloss/xtensa/nano.specs
@@ -0,0 +1,18 @@
+%rename link nano_link
+%rename link_gcc_c_sequence nano_link_gcc_c_sequence
+
+*nano_libc:
+-lc_nano
+
+*nano_libgloss:
+%{specs=nosys.specs:-lnosys}
+
+*link_gcc_c_sequence:
+%(nano_link_gcc_c_sequence) --start-group %G %(nano_libc) %(nano_libgloss) --end-group
+
+*link:
+%(nano_link) %:replace-outfile(-lc -lc_nano) %:replace-outfile(-lg -lg_nano) %:replace-outfile(-lm -lm_nano)
+
+*lib:
+%{!shared:%{g*:-lg_nano} %{!p:%{!pg:-lc_nano}}%{p:-lc_p}%{pg:-lc_p}}
+
diff --git a/libgloss/xtensa/sim-call.S b/libgloss/xtensa/sim-call.S
new file mode 100644
index 000000000..646885426
--- /dev/null
+++ b/libgloss/xtensa/sim-call.S
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+ .type __sim_call, @function
+ .align 4
+ .global __sim_call
+__sim_call:
+ entry a1, 32
+ simcall
+ retw
diff --git a/libgloss/xtensa/sim-vectors.S b/libgloss/xtensa/sim-vectors.S
new file mode 100644
index 000000000..73eea7b18
--- /dev/null
+++ b/libgloss/xtensa/sim-vectors.S
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2015-2019 Cadence Design Systems, Inc.
+ *
+ * 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 <xtensa/config/core-isa.h>
+#include <syscalls.h>
+
+//#define PS_OWB_SHIFT 8
+//#define PS_OWB_BITS 4
+//#define EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (MOVSP instruction) for alloca */
+
+#if XCHAL_HAVE_L32R
+ .section .rodata
+_sim_panic_msg:
+ .ascii "PANIC: Unhandled exception!\n"
+ _sim_panic_msg_len = . - _sim_panic_msg
+
+ .section .text
+ .literal .Lpanic_msg, _sim_panic_msg
+ .literal .Lpanic_msg_len, _sim_panic_msg_len
+ .align 4
+_xt_unhandled_exc:
+ movi a2, SYS_write
+ movi a3, 2
+ l32r a4, .Lpanic_msg
+ l32r a5, .Lpanic_msg_len
+ simcall
+#else
+_xt_unhandled_exc:
+#endif
+ movi a2, SYS_exit
+ movi a3, 1
+ simcall
+
+/*
+--------------------------------------------------------------------------------
+Handle alloca exception generated by interruptee executing 'movsp'.
+This uses space between the window vectors, so is essentially "free".
+All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
+and PS.EXCM has been set by the exception hardware (can't be interrupted).
+The fact the alloca exception was taken means the registers associated with
+the base-save area have been spilled and will be restored by the underflow
+handler, so those 4 registers are available for scratch.
+The code is optimized to avoid unaligned branches and minimize cache misses.
+--------------------------------------------------------------------------------
+*/
+
+ #if XCHAL_HAVE_WINDOWED
+ .section .text
+ .global _xt_alloca_exc
+ .align 4
+_xt_alloca_exc:
+
+ rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */
+ rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */
+ rsr a2, PS
+ extui a3, a2, 8/*PS_OWB_BITS*/, 4/*PS_OWB_BITS*/
+ xor a3, a3, a4 /* bits changed from old to current windowbase */
+ rsr a4, EXCSAVE1 /* restore original a0 (now in a4) */
+ slli a3, a3, 8
+ xor a2, a2, a3 /* flip changed bits in old window base */
+ wsr a2, PS /* update PS.OWB to new window base */
+ rsync
+
+ bbci.l a4, 31, _WindowUnderflow4
+ rotw -1 /* original a0 goes to a8 */
+ bbci.l a8, 30, _WindowUnderflow8
+ rotw -1
+ j _WindowUnderflow12
+ #endif
+
+
+/*
+--------------------------------------------------------------------------------
+ User exception handler.
+--------------------------------------------------------------------------------
+*/
+
+ #if XCHAL_HAVE_WINDOWED
+ .section .text
+ .align 4
+_xt_to_alloca_exc:
+ j _xt_alloca_exc /* in window vectors section */
+ #endif
+
+ .type _xt_user_exc,@function
+ .align 4
+_xt_user_exc:
+
+ rsr a0, EXCCAUSE
+ /* Handle alloca and syscall exceptions */
+ #if XCHAL_HAVE_WINDOWED
+ beqi a0, 5/*EXCCAUSE_ALLOCA*/, _xt_to_alloca_exc
+ #endif
+ j _xt_unhandled_exc
+
+
+/*
+--------------------------------------------------------------------------------
+NMI Exception
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .NMIExceptionVector
+ .section .NMIExceptionVector.text, "ax"
+ .global NMIExceptionVector
+ .type NMIExceptionVector,@function
+ .align 4
+
+NMIExceptionVector:
+ j _xt_unhandled_exc
+
+ .end literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+Kernel Exception
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .KernelExceptionVector
+ .section .KernelExceptionVector.text, "ax"
+ .global KernelExceptionVector
+ .type KernelExceptionVector,@function
+ .align 4
+
+KernelExceptionVector:
+ j _xt_unhandled_exc
+
+ .end literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+User Exception
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .UserExceptionVector
+ .section .UserExceptionVector.text, "ax"
+ .global _UserExceptionVector
+ .type _UserExceptionVector,@function
+ .align 4
+
+_UserExceptionVector:
+
+ wsr a0, EXCSAVE1 /* preserve a0 */
+ j _xt_user_exc /* user exception handler */
+ /* never returns here - call0 is used as a jump (see note at top) */
+
+ .end literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+Double Exception
+--------------------------------------------------------------------------------
+*/
+
+ .begin literal_prefix .DoubleExceptionVector
+ .section .DoubleExceptionVector.text, "ax"
+ .global DoubleExceptionVector
+ .type DoubleExceptionVector,@function
+ .align 4
+
+DoubleExceptionVector:
+ j _xt_unhandled_exc
+
+ .end literal_prefix
diff --git a/libgloss/xtensa/sim.elf.specs b/libgloss/xtensa/sim.elf.specs
new file mode 100644
index 000000000..3024f6887
--- /dev/null
+++ b/libgloss/xtensa/sim.elf.specs
@@ -0,0 +1,5 @@
+*startfile:
+crt1-sim%O%s
+
+*lib:
+-lc --whole-archive -lgloss --no-whole-archive -lpthread_stubs -lc %Tmemory.elf.ld %Tapp.elf.ld
diff --git a/libgloss/xtensa/sleep.S b/libgloss/xtensa/sleep.S
new file mode 100644
index 000000000..2f20a61b5
--- /dev/null
+++ b/libgloss/xtensa/sleep.S
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <soc/cpu.h>
+
+#define USECONDS_IN_SECOND 1000000
+
+ .type sleep, @function
+ .align 4
+ .global sleep
+sleep:
+ entry a1, 0x30
+ mov.n a7, a1
+ s32i.n a2, a7, 0
+
+ mov a3, a2
+.Lsleep_delay_second:
+ addi a3, a3, -1
+ movi a10, USECONDS_IN_SECOND
+ call8 usleep
+ bnez a3, .Lsleep_delay_second
+
+.Lsleep_exit:
+ s32i.n a2, a7, 0
+ retw
+
+
+ .type usleep, @function
+ .align 4
+ .global usleep
+usleep:
+ entry a1, 0x30
+ mov.n a7, a1
+ s32i.n a2, a7, 0
+
+ /* convert time to CLOCK ticks per 1us */
+ movi a6, CPU_FREQUENCY_MHZ // CPU_FREQUENCY_MHZ == ticks per us
+ mull a2, a2, a6
+
+ /*
+ * Registers purpose:
+ * a3 - start CCOUNT value
+ * a4 - current CCOUNT value
+ * a5 - target CCOUNT value
+ */
+
+ rsr a3, CCOUNT
+ add a5, a3, a2
+ bgeu a5, a3, .Lusleep_waitloop
+
+.Lusleep_waitoverflow:
+ /* you are here because a5 (target CCOUNT) was overflown
+ * it means that we need to wait CCOUNT register overflow
+ * before do main loop
+ */
+ rsr a4, CCOUNT
+ bgeu a4, a3, .Lusleep_waitoverflow
+
+.Lusleep_waitloop:
+ /* wait until we reach target CCOUNT value */
+ rsr a4, CCOUNT
+ bgeu a4, a5, .Lusleep_exit
+ j .Lusleep_waitloop
+.Lusleep_exit:
+ s32i.n a2, a7, 0
+ retw
+
diff --git a/libgloss/xtensa/sys.openocd.specs b/libgloss/xtensa/sys.openocd.specs
new file mode 100644
index 000000000..457318424
--- /dev/null
+++ b/libgloss/xtensa/sys.openocd.specs
@@ -0,0 +1,8 @@
+%rename link_gcc_c_sequence openocd_link_gcc_c_sequence
+
+*libopenocd:
+--whole-archive -lsys_openocd --no-whole-archive
+
+*link_gcc_c_sequence:
+%(openocd_link_gcc_c_sequence) --start-group %G %(libopenocd) --end-group
+
diff --git a/libgloss/xtensa/sys.qemu.specs b/libgloss/xtensa/sys.qemu.specs
new file mode 100644
index 000000000..5185c0480
--- /dev/null
+++ b/libgloss/xtensa/sys.qemu.specs
@@ -0,0 +1,8 @@
+%rename link_gcc_c_sequence qemu_link_gcc_c_sequence
+
+*libqemu:
+--whole-archive -lsys_qemu --no-whole-archive
+
+*link_gcc_c_sequence:
+%(qemu_link_gcc_c_sequence) --start-group %G %(libqemu) --end-group
+
diff --git a/libgloss/xtensa/syscalls.c b/libgloss/xtensa/syscalls.c
new file mode 100644
index 000000000..11e972c3f
--- /dev/null
+++ b/libgloss/xtensa/syscalls.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2023 Espressif Systems (Shanghai) CO LTD
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <unistd.h>
+#include <syscalls.h>
+#include <sys/stat.h>
+#include <soc/uart.h>
+
+#if defined (OPENOCD_SEMIHOSTING) || (QEMU_SEMIHOSTING)
+# define WITH_SEMIHOSTING
+# define __WEAK_FUNCTION_ATTR__
+#else
+# define __WEAK_FUNCTION_ATTR__ __attribute__((__weak__))
+#endif
+
+
+/* __semihosting_call is a function in case semihosting usage, macro (-1) otherwise */
+#ifdef WITH_SEMIHOSTING
+
+static inline int
+__attribute__ ((always_inline))
+__semihosting_call(int id, int arg1, int arg2, int arg3, int arg4)
+{
+# ifdef OPENOCD_SEMIHOSTING
+ register long a2 asm("a2") = id;
+ long args[] = {arg1, arg2, arg3, arg4};
+ register long a3 asm("a3") = (long)&args;
+
+ /* OpenOCD has different semihosting api for sys_exit on 32-bit and 64-bit */
+ if (id == SYS_exit && sizeof(void *) != 8) {
+ a3 = ADP_STOPPED_APPLICATION_EXIT;
+ }
+ __asm__ __volatile__ (
+ "break 1, 14\n"
+ : "+r"(a2): "r"(a3)
+ : "memory");
+
+ // return code is placed in a2 register, so return it to the caller
+ return a2;
+# else // OPENOCD_SEMIHOSTING
+ extern int __sim_call(int id, int arg1, int arg2, int arg3, int arg4);
+ return __sim_call(id, arg1, arg2, arg3, arg4);
+# endif // OPENOCD_SEMIHOSTING
+}
+
+# ifdef OPENOCD_SEMIHOSTING
+
+int
+__semihosting_init (void)
+{
+ struct {
+ int version;
+ } ver_info = { 2 };
+ __semihosting_call(ESP_SEMIHOSTING_SYS_DRV_INFO, (long) &ver_info, sizeof(ver_info), 0, 0);
+}
+
+# endif // OPENOCD_SEMIHOSTING
+
+#else // !WITH_SEMIHOSTING
+# define __semihosting_call(...) (-1)
+#endif // WITH_SEMIHOSTING
+
+
+void
+__WEAK_FUNCTION_ATTR__
+__attribute__ ((noreturn))
+_exit (int status)
+{
+ __semihosting_call(SYS_exit, status, 0, 0, 0);
+
+ for (;;) {
+ ;
+ }
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_open (const char *file, int flags, int mode)
+{
+ return __semihosting_call(SYS_open, (int) file, flags, mode, 0);
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_lseek (int fd, _off_t off, int whence)
+{
+ return __semihosting_call(SYS_lseek, fd, off, whence, 0);
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_close (int fd)
+{
+ return __semihosting_call(SYS_close, fd, 0, 0, 0);
+}
+
+
+_ssize_t
+__WEAK_FUNCTION_ATTR__
+_write (int fd, const char *buf, size_t cnt)
+{
+ int ret = 0;
+#ifdef WITH_SEMIHOSTING
+ ret = __semihosting_call(SYS_write, fd, (int) buf, cnt, 0);
+# ifdef OPENOCD_SEMIHOSTING
+ /* ret - number of bytes that are NOT written. Calculate written */
+ ret = cnt - ret;
+# endif // OPENOCD_SEMIHOSTING
+#else // !WITH_SEMIHOSTING
+ if (fd != STDOUT_FILENO && fd != STDERR_FILENO) {
+ return -1;
+ }
+
+ for (uint32_t i = 0; i < cnt; i++) {
+ board_uart_write_char(buf[i]);
+ }
+ ret = cnt;
+#endif // WITH_SEMIHOSTING
+ return ret;
+}
+
+
+/* Do not compile functions with common implementation
+ * if building semihosting library
+ */
+#ifndef WITH_SEMIHOSTING
+
+struct _reent*
+__WEAK_FUNCTION_ATTR__
+__getreent(void)
+{
+ return _GLOBAL_REENT;
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_fstat (int fd, struct stat *pstat)
+{
+
+ if (fd < STDERR_FILENO)
+ {
+ pstat->st_mode = S_IFCHR;
+ return 0;
+ }
+ return -1;
+}
+
+
+_ssize_t
+__WEAK_FUNCTION_ATTR__
+_read (int fd, char *buf, size_t cnt)
+{
+ return -1;
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_getpid (void)
+{
+ return -1;
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+_kill (int sig)
+{
+ return -1;
+}
+
+
+void *
+__WEAK_FUNCTION_ATTR__
+_sbrk (int incr)
+{
+ extern char end; /* Set by linker. */
+ static char * heap_end;
+ char * prev_heap_end;
+
+ if (heap_end == 0) {
+ heap_end = & end;
+ }
+
+ prev_heap_end = heap_end;
+ heap_end += incr;
+
+ return (void *) prev_heap_end;
+}
+
+
+int
+__WEAK_FUNCTION_ATTR__
+pthread_setcancelstate (int state, int *oldstate)
+{
+ return 0;
+}
+
+#endif // WITH_SEMIHOSTING
diff --git a/libgloss/xtensa/window-vectors.S b/libgloss/xtensa/window-vectors.S
new file mode 100644
index 000000000..acab8b355
--- /dev/null
+++ b/libgloss/xtensa/window-vectors.S
@@ -0,0 +1,252 @@
+// window-vectors-new.S - Register Window Overflow/Underflow Handlers for XEA2
+// $Id: //depot/rel/Eaglenest/Xtensa/OS/xtos/window-vectors-new.S#3 $
+
+// Copyright (c) 1999-2013 Tensilica Inc.
+//
+// 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.
+
+// Exports
+.global _WindowOverflow4
+.global _WindowUnderflow4
+.global _WindowOverflow8
+.global _WindowUnderflow8
+.global _WindowOverflow12
+.global _WindowUnderflow12
+
+ // Note: the current window exception vectors do not generate any
+ // literals. Hence the literal_prefix directive is not necessary.
+ // Specifying it "just in case" creates an empty section (named
+ // ".WindowVectors.literal") which can in some cases cause linking
+ // problems (the linker scripts don't place it anywhere).
+ // So leave it commented out:
+ //
+ //.begin literal_prefix .WindowVectors
+
+ .section .WindowVectors.text, "ax"
+
+//
+// GENERAL NOTES:
+//
+// These window exception handlers need not be modified.
+// They are specific to the windowed call ABI only.
+//
+// Underflow Handlers:
+//
+// The underflow handler for returning from call[i+1] to call[i]
+// must preserve all the registers from call[i+1]'s window.
+// In particular, a0 and a1 must be preserved because the RETW instruction
+// will be reexecuted (and may even underflow again if an intervening
+// exception has flushed call[i]'s registers).
+// Registers a2 and up may contain return values.
+//
+// The caller could also potentially assume that the callee's a0 and a1
+// (its own a4&a5 if call4, a8&a9 if call8, a12&a13 if call12)
+// are correct for whatever reason (not a clean thing to do in general,
+// but if it's possible, unless the ABI explicitly prohibits it,
+// it will eventually be done :) -- whether the the ABI needs to
+// prohibit this is a different question).
+//
+// Timing of Handlers:
+//
+// Here is an overview of the overhead of taking a window exception,
+// ie. the number of additional cycles taken relative to case where
+// an exception is not taken.
+// NOTE: these numbers do not take into account any cache misses,
+// write buffer stalls, or other external stalls, if they occur.
+// The totals consist of 5 cycles to enter the handler (or 6 or 7
+// for optional longer pipelines in Xtensa LX), the number of instructions
+// and interlocks (2nd and 3rd columns below), and 2 cycles jump delay
+// on return (3 cycles for optional longer I-side pipeline in Xtensa LX):
+//
+// Instruction+bubbles Totals (5-stage)
+// XEA1 XEA2 XEA1 XEA2
+// Overflow-4 7 5 14 12
+// Overflow-8 14 10 21 17
+// Overflow-12 18 14 25 21
+// Underflow-4 6 5 13 12
+// Underflow-8 14 10 21 17
+// Underflow-12 18 14 25 21
+//
+// Underflow-8 15 12 25 22 (7-stage; could be made 1 less)
+// Underflow-12 19 16 29 26 (7-stage; could be made 1 less)
+
+
+// 4-Register Window Overflow Vector (Handler)
+//
+// Invoked if a call[i] referenced a register (a4-a15)
+// that contains data from ancestor call[j];
+// call[j] had done a call4 to call[j+1].
+// On entry here:
+// window rotated to call[j] start point;
+// a0-a3 are registers to be saved;
+// a4-a15 must be preserved;
+// a5 is call[j+1]'s stack pointer.
+
+ .org 0x0
+_WindowOverflow4:
+ s32e a0, a5, -16 // save a0 to call[j+1]'s stack frame
+ s32e a1, a5, -12 // save a1 to call[j+1]'s stack frame
+ s32e a2, a5, -8 // save a2 to call[j+1]'s stack frame
+ s32e a3, a5, -4 // save a3 to call[j+1]'s stack frame
+ rfwo // rotates back to call[i] position
+
+ .size _WindowOverflow4, . - _WindowOverflow4
+
+
+// 4-Register Window Underflow Vector (Handler)
+//
+// Invoked by RETW returning from call[i+1] to call[i]
+// where call[i]'s registers must be reloaded (not live in ARs);
+// call[i] had done a call4 to call[i+1].
+// On entry here:
+// window rotated to call[i] start point;
+// a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
+// a4-a15 must be preserved (they are call[i+1].reg[0..11]);
+// a5 is call[i+1]'s stack pointer.
+
+ .org 0x40
+_WindowUnderflow4:
+ l32e a0, a5, -16 // restore a0 from call[i+1]'s stack frame
+ l32e a1, a5, -12 // restore a1 from call[i+1]'s stack frame
+ l32e a2, a5, -8 // restore a2 from call[i+1]'s stack frame
+ l32e a3, a5, -4 // restore a3 from call[i+1]'s stack frame
+ rfwu
+
+ .size _WindowUnderflow4, . - _WindowUnderflow4
+
+
+// 8-Register Window Overflow Vector (Handler)
+//
+// Invoked if a call[i] referenced a register (a4-a15)
+// that contains data from ancestor call[j];
+// call[j] had done a call8 to call[j+1].
+// On entry here:
+// window rotated to call[j] start point;
+// a0-a7 are registers to be saved;
+// a8-a15 must be preserved;
+// a9 is call[j+1]'s stack pointer.
+
+ .org 0x80
+_WindowOverflow8:
+ s32e a0, a9, -16 // save a0 to call[j+1]'s stack frame
+ l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame)
+ s32e a1, a9, -12 // save a1 to call[j+1]'s stack frame
+ s32e a2, a9, -8 // save a2 to call[j+1]'s stack frame
+ s32e a3, a9, -4 // save a3 to call[j+1]'s stack frame
+ s32e a4, a0, -32 // save a4 to call[j]'s stack frame
+ s32e a5, a0, -28 // save a5 to call[j]'s stack frame
+ s32e a6, a0, -24 // save a6 to call[j]'s stack frame
+ s32e a7, a0, -20 // save a7 to call[j]'s stack frame
+ rfwo // rotates back to call[i] position
+
+ .size _WindowOverflow8, . - _WindowOverflow8
+
+
+// 8-Register Window Underflow Vector (Handler)
+//
+// Invoked by RETW returning from call[i+1] to call[i]
+// where call[i]'s registers must be reloaded (not live in ARs);
+// call[i] had done a call8 to call[i+1].
+// On entry here:
+// window rotated to call[i] start point;
+// a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
+// a8-a15 must be preserved (they are call[i+1].reg[0..7]);
+// a9 is call[i+1]'s stack pointer.
+
+ .org 0xC0
+_WindowUnderflow8:
+ l32e a0, a9, -16 // restore a0 from call[i+1]'s stack frame
+ l32e a1, a9, -12 // restore a1 from call[i+1]'s stack frame
+ l32e a2, a9, -8 // restore a2 from call[i+1]'s stack frame
+ l32e a7, a1, -12 // a7 <- call[i-1]'s sp (used to find end of call[i]'s frame)
+ l32e a3, a9, -4 // restore a3 from call[i+1]'s stack frame
+ l32e a4, a7, -32 // restore a4 from call[i]'s stack frame
+ l32e a5, a7, -28 // restore a5 from call[i]'s stack frame
+ l32e a6, a7, -24 // restore a6 from call[i]'s stack frame../../.././libgloss/xtensa/window-vectors.S
+ l32e a7, a7, -20 // restore a7 from call[i]'s stack frame
+ rfwu
+
+ .size _WindowUnderflow8, . - _WindowUnderflow8
+
+
+// 12-Register Window Overflow Vector (Handler)
+//
+// Invoked if a call[i] referenced a register (a4-a15)
+// that contains data from ancestor call[j];
+// call[j] had done a call12 to call[j+1].
+// On entry here:
+// window rotated to call[j] start point;
+// a0-a11 are registers to be saved;
+// a12-a15 must be preserved;
+// a13 is call[j+1]'s stack pointer.
+
+ .org 0x100
+_WindowOverflow12:
+ s32e a0, a13, -16 // save a0 to call[j+1]'s stack frame
+ l32e a0, a1, -12 // a0 <- call[j-1]'s sp (used to find end of call[j]'s frame)
+ s32e a1, a13, -12 // save a1 to call[j+1]'s stack frame
+ s32e a2, a13, -8 // save a2 to call[j+1]'s stack frame
+ s32e a3, a13, -4 // save a3 to call[j+1]'s stack frame
+ s32e a4, a0, -48 // save a4 to end of call[j]'s stack frame
+ s32e a5, a0, -44 // save a5 to end of call[j]'s stack frame
+ s32e a6, a0, -40 // save a6 to end of call[j]'s stack frame
+ s32e a7, a0, -36 // save a7 to end of call[j]'s stack frame
+ s32e a8, a0, -32 // save a8 to end of call[j]'s stack frame
+ s32e a9, a0, -28 // save a9 to end of call[j]'s stack frame
+ s32e a10, a0, -24 // save a10 to end of call[j]'s stack frame
+ s32e a11, a0, -20 // save a11 to end of call[j]'s stack frame
+ rfwo // rotates back to call[i] position
+
+ .size _WindowOverflow12, . - _WindowOverflow12
+
+
+// 12-Register Window Underflow Vector (Handler)
+//
+// Invoked by RETW returning from call[i+1] to call[i]
+// where call[i]'s registers must be reloaded (not live in ARs);
+// call[i] had done a call12 to call[i+1].
+// On entry here:
+// window rotated to call[i] start point;
+// a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
+// a12-a15 must be preserved (they are call[i+1].reg[0..3]);
+// a13 is call[i+1]'s stack pointer.
+
+ .org 0x140
+_WindowUnderflow12:
+ l32e a0, a13, -16 // restore a0 from call[i+1]'s stack frame
+ l32e a1, a13, -12 // restore a1 from call[i+1]'s stack frame
+ l32e a2, a13, -8 // restore a2 from call[i+1]'s stack frame
+ l32e a11, a1, -12 // a11 <- call[i-1]'s sp (used to find end of call[i]'s frame)
+ l32e a3, a13, -4 // restore a3 from call[i+1]'s stack frame
+ l32e a4, a11, -48 // restore a4 from end of call[i]'s stack frame
+ l32e a5, a11, -44 // restore a5 from end of call[i]'s stack frame
+ l32e a6, a11, -40 // restore a6 from end of call[i]'s stack frame
+ l32e a7, a11, -36 // restore a7 from end of call[i]'s stack frame
+ l32e a8, a11, -32 // restore a8 from end of call[i]'s stack frame
+ l32e a9, a11, -28 // restore a9 from end of call[i]'s stack frame
+ l32e a10, a11, -24 // restore a10 from end of call[i]'s stack frame
+ l32e a11, a11, -20 // restore a11 from end of call[i]'s stack frame
+ rfwu
+
+ .size _WindowUnderflow12, . - _WindowUnderflow12
+
+
+ //.end literal_prefix
+ .text