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:
authorTamar Christina <tamar.christina@arm.com>2017-07-05 15:04:07 +0300
committerCorinna Vinschen <corinna@vinschen.de>2017-07-05 15:41:27 +0300
commitd7d6ad7b6b7e740992dbb519962c4fc344e1d58c (patch)
treeffaa1d73dda4be34d0908699df9c1c94417c3b6d /libgloss/arm
parentcc142edbe7af2f7d52a80b137ac0ad141408033d (diff)
Add support for Semihosting v2 support for ARM in libgloss.
Semihosting v2 changes are documented here: https://developer.arm.com/docs/100863/latest/ The biggest change is the addition of an extensions mechanism to add more extensions in the future. Signed-off-by: Tamar Christina <tamar.christina@arm.com>
Diffstat (limited to 'libgloss/arm')
-rw-r--r--libgloss/arm/_kill.c29
-rw-r--r--libgloss/arm/swi.h98
-rw-r--r--libgloss/arm/syscalls.c169
3 files changed, 231 insertions, 65 deletions
diff --git a/libgloss/arm/_kill.c b/libgloss/arm/_kill.c
index 81354d473..8871d3c36 100644
--- a/libgloss/arm/_kill.c
+++ b/libgloss/arm/_kill.c
@@ -10,15 +10,36 @@ _kill (int pid, int sig)
(void) pid; (void) sig;
#ifdef ARM_RDI_MONITOR
/* Note: The pid argument is thrown away. */
+ int block[2];
+ block[1] = sig;
+ int insn;
+
+#if SEMIHOST_V2
+ if (_has_ext_exit_extended ())
+ {
+ insn = AngelSWI_Reason_ReportExceptionExtended;
+ }
+ else
+#endif
+ {
+ insn = AngelSWI_Reason_ReportException;
+ }
+
switch (sig)
{
case SIGABRT:
- return do_AngelSWI (AngelSWI_Reason_ReportException,
- (void *) ADP_Stopped_RunTimeError);
+ {
+ block[0] = ADP_Stopped_RunTimeError;
+ break;
+ }
default:
- return do_AngelSWI (AngelSWI_Reason_ReportException,
- (void *) ADP_Stopped_ApplicationExit);
+ {
+ block[0] = ADP_Stopped_ApplicationExit;
+ break;
+ }
}
+
+ return do_AngelSWI (insn, block);
#else
asm ("swi %a0" :: "i" (SWI_Exit));
#endif
diff --git a/libgloss/arm/swi.h b/libgloss/arm/swi.h
index b7fa243f8..72cb838dc 100644
--- a/libgloss/arm/swi.h
+++ b/libgloss/arm/swi.h
@@ -1,4 +1,5 @@
#include "arm.h"
+#include <_ansi.h>
/* SWI numbers for RDP (Demon) monitor. */
#define SWI_WriteC 0x0
@@ -29,45 +30,76 @@
/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
-#define AngelSWI_ARM 0x123456
-#ifdef __thumb__
-#define AngelSWI 0xAB
-#else
-#define AngelSWI AngelSWI_ARM
-#endif
+#if defined (SEMIHOST_V2) && defined (SEMIHOST_V2_MIXED_MODE)
+ #define AngelSWI_ARM 0xF000 /* HLT A32. */
+ #ifdef __thumb__
+ #define AngelSWI 0x3C /* HLT T32. */
+ #else /* __thumb__. */
+ #define AngelSWI AngelSWI_ARM
+ #endif /* __thumb__. */
+#else /* SEMIHOST_V2. */
+ #define AngelSWI_ARM 0x123456 /* SVC A32. */
+ #ifdef __thumb__
+ #define AngelSWI 0xAB /* SVC T32. */
+ #else /* __thumb__. */
+ #define AngelSWI AngelSWI_ARM
+ #endif /* __thumb__. */
+#endif /* SEMIHOST_V2. */
+
/* For thumb only architectures use the BKPT instruction instead of SWI. */
#ifdef THUMB_VXM
-#define AngelSWIInsn "bkpt"
-#define AngelSWIAsm bkpt
+ #define AngelSWIInsn "bkpt"
+ #define AngelSWIAsm bkpt
#else
-#define AngelSWIInsn "swi"
-#define AngelSWIAsm swi
+ #define AngelSWIInsn "swi"
+ #define AngelSWIAsm swi
#endif
/* The reason codes: */
-#define AngelSWI_Reason_Open 0x01
-#define AngelSWI_Reason_Close 0x02
-#define AngelSWI_Reason_WriteC 0x03
-#define AngelSWI_Reason_Write0 0x04
-#define AngelSWI_Reason_Write 0x05
-#define AngelSWI_Reason_Read 0x06
-#define AngelSWI_Reason_ReadC 0x07
-#define AngelSWI_Reason_IsTTY 0x09
-#define AngelSWI_Reason_Seek 0x0A
-#define AngelSWI_Reason_FLen 0x0C
-#define AngelSWI_Reason_TmpNam 0x0D
-#define AngelSWI_Reason_Remove 0x0E
-#define AngelSWI_Reason_Rename 0x0F
-#define AngelSWI_Reason_Clock 0x10
-#define AngelSWI_Reason_Time 0x11
-#define AngelSWI_Reason_System 0x12
-#define AngelSWI_Reason_Errno 0x13
-#define AngelSWI_Reason_GetCmdLine 0x15
-#define AngelSWI_Reason_HeapInfo 0x16
-#define AngelSWI_Reason_EnterSVC 0x17
-#define AngelSWI_Reason_ReportException 0x18
-#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
-#define ADP_Stopped_RunTimeError ((2 << 16) + 35)
+#define AngelSWI_Reason_Open 0x01
+#define AngelSWI_Reason_Close 0x02
+#define AngelSWI_Reason_WriteC 0x03
+#define AngelSWI_Reason_Write0 0x04
+#define AngelSWI_Reason_Write 0x05
+#define AngelSWI_Reason_Read 0x06
+#define AngelSWI_Reason_ReadC 0x07
+#define AngelSWI_Reason_IsError 0x08
+#define AngelSWI_Reason_IsTTY 0x09
+#define AngelSWI_Reason_Seek 0x0A
+#define AngelSWI_Reason_FLen 0x0C
+#define AngelSWI_Reason_TmpNam 0x0D
+#define AngelSWI_Reason_Remove 0x0E
+#define AngelSWI_Reason_Rename 0x0F
+#define AngelSWI_Reason_Clock 0x10
+#define AngelSWI_Reason_Time 0x11
+#define AngelSWI_Reason_System 0x12
+#define AngelSWI_Reason_Errno 0x13
+#define AngelSWI_Reason_GetCmdLine 0x15
+#define AngelSWI_Reason_HeapInfo 0x16
+#define AngelSWI_Reason_EnterSVC 0x17
+#define AngelSWI_Reason_ReportException 0x18
+#define AngelSWI_Reason_ReportExceptionExtended 0x20
+#define AngelSWI_Reason_Elapsed 0x30
+#define AngelSWI_Reason_TickFreq 0x31
+#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
+#define ADP_Stopped_RunTimeError ((2 << 16) + 35)
+
+/* Semihosting feature magic numbers. */
+#define NUM_SHFB_MAGIC 4
+#define SHFB_MAGIC_0 0x53
+#define SHFB_MAGIC_1 0x48
+#define SHFB_MAGIC_2 0x46
+#define SHFB_MAGIC_3 0x42
+
+/* Semihosting extensions. */
+#define SH_EXT_EXIT_EXTENDED_BITNUM 0x0
+#define SH_EXT_STDOUT_STDERR_BITNUM 0x1
+
+#if !defined (__ASSEMBLER__)
+extern int _get_semihosting_exts _PARAMS ((char*, int, int));
+extern int _has_ext_exit_extended _PARAMS ((void));
+extern int _has_ext_stdout_stderr _PARAMS ((void));
+#endif
#if defined(ARM_RDI_MONITOR) && !defined(__ASSEMBLER__)
diff --git a/libgloss/arm/syscalls.c b/libgloss/arm/syscalls.c
index 0ccad215c..80713680b 100644
--- a/libgloss/arm/syscalls.c
+++ b/libgloss/arm/syscalls.c
@@ -47,6 +47,9 @@ static int checkerror _PARAMS ((int));
static int error _PARAMS ((int));
static int get_errno _PARAMS ((void));
+/* Semihosting utilities. */
+static void initialise_semihosting_exts _PARAMS ((void));
+
/* Struct used to keep track of the file position, just so we
can implement fseek(fh,x,SEEK_CUR). */
struct fdent
@@ -95,6 +98,9 @@ static int monitor_stdin;
static int monitor_stdout;
static int monitor_stderr;
+static int supports_ext_exit_extended = -1;
+static int supports_ext_stdout_stderr = -1;
+
/* Return a pointer to the structure associated with
the user file descriptor fd. */
static struct fdent*
@@ -154,15 +160,21 @@ initialise_monitor_handles (void)
block[1] = 0; /* mode "r" */
monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
- block[0] = (int) ":tt";
- block[2] = 3; /* length of filename */
- block[1] = 4; /* mode "w" */
- monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+ for (i = 0; i < MAX_OPEN_FILES; i ++)
+ openfiles[i].handle = -1;
- block[0] = (int) ":tt";
- block[2] = 3; /* length of filename */
- block[1] = 8; /* mode "a" */
- monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+ if (_has_ext_stdout_stderr ())
+ {
+ block[0] = (int) ":tt";
+ block[2] = 3; /* length of filename */
+ block[1] = 4; /* mode "w" */
+ monitor_stdout = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+
+ block[0] = (int) ":tt";
+ block[2] = 3; /* length of filename */
+ block[1] = 8; /* mode "a" */
+ monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
+ }
#else
int fh;
const char * name;
@@ -174,34 +186,135 @@ initialise_monitor_handles (void)
: "r0","r1");
monitor_stdin = fh;
- name = ":tt";
- asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
- : "=r"(fh)
- : "i" (SWI_Open),"r"(name)
- : "r0","r1");
- monitor_stdout = fh;
-
- name = ":tt";
- asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
- : "=r"(fh)
- : "i" (SWI_Open),"r"(name)
- : "r0","r1");
- monitor_stderr = fh;
+ if (_has_ext_stdout_stderr ())
+ {
+ name = ":tt";
+ asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
+ : "=r"(fh)
+ : "i" (SWI_Open),"r"(name)
+ : "r0","r1");
+ monitor_stdout = fh;
+
+ name = ":tt";
+ asm ("mov r0,%2; mov r1, #8; swi %a1; mov %0, r0"
+ : "=r"(fh)
+ : "i" (SWI_Open),"r"(name)
+ : "r0","r1");
+ monitor_stderr = fh;
+ }
#endif
/* If we failed to open stderr, redirect to stdout. */
if (monitor_stderr == -1)
monitor_stderr = monitor_stdout;
- for (i = 0; i < MAX_OPEN_FILES; i ++)
- openfiles[i].handle = -1;
-
openfiles[0].handle = monitor_stdin;
openfiles[0].pos = 0;
- openfiles[1].handle = monitor_stdout;
- openfiles[1].pos = 0;
- openfiles[2].handle = monitor_stderr;
- openfiles[2].pos = 0;
+
+ if (_has_ext_stdout_stderr ())
+ {
+ openfiles[1].handle = monitor_stdout;
+ openfiles[1].pos = 0;
+ openfiles[2].handle = monitor_stderr;
+ openfiles[2].pos = 0;
+ }
+}
+
+int
+_has_ext_exit_extended (void)
+{
+ if (supports_ext_exit_extended < 0)
+ {
+ initialise_semihosting_exts ();
+ }
+
+ return supports_ext_exit_extended;
+}
+
+int
+_has_ext_stdout_stderr (void)
+{
+ if (supports_ext_stdout_stderr < 0)
+ {
+ initialise_semihosting_exts ();
+ }
+
+ return supports_ext_stdout_stderr;
+}
+
+static void
+initialise_semihosting_exts (void)
+{
+ supports_ext_exit_extended = 0;
+ supports_ext_stdout_stderr = 1;
+
+#if SEMIHOST_V2
+ char features[1];
+ if (_get_semihosting_exts (features, 0, 1) > 0)
+ {
+ supports_ext_exit_extended
+ = features[0] & (1 << SH_EXT_EXIT_EXTENDED_BITNUM);
+ supports_ext_stdout_stderr
+ = features[0] & (1 << SH_EXT_STDOUT_STDERR_BITNUM);
+ }
+#endif
+}
+
+int
+_get_semihosting_exts (char* features, int offset, int num)
+{
+ int len;
+ struct fdent *pfd;
+ int fd = _open (":semihosting-features", O_RDONLY);
+ memset (features, 0, num);
+
+ if (fd == -1)
+ {
+ return -1;
+ }
+
+ pfd = findslot (fd);
+
+#ifdef ARM_RDI_MONITOR
+ len = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
+#else
+ asm ("mov r0,%2; swi %a1; mov %0, r0"
+ : "=r"(len)
+ : "i" (SWI_Flen),"r"(pfd->handle)
+ : "r0");
+#endif
+
+ if (len < NUM_SHFB_MAGIC
+ || num > (len - NUM_SHFB_MAGIC))
+ {
+ _close (fd);
+ return -1;
+ }
+
+ char buffer[NUM_SHFB_MAGIC];
+ int n_read = _read (fd, buffer, NUM_SHFB_MAGIC);
+
+ if (n_read < NUM_SHFB_MAGIC
+ || buffer[0] != SHFB_MAGIC_0
+ || buffer[1] != SHFB_MAGIC_1
+ || buffer[2] != SHFB_MAGIC_2
+ || buffer[3] != SHFB_MAGIC_3)
+ {
+ _close (fd);
+ return -1;
+ }
+
+ if (_lseek (fd, offset, SEEK_CUR) < 0)
+ {
+ _close (fd);
+ return -1;
+ }
+
+ n_read = _read (fd, features, num);
+
+ _close (fd);
+
+ return checkerror (n_read);
}
static int