]> sourceware.org Git - newlib-cygwin.git/commitdiff
Add support for Semihosting v2 support for ARM in libgloss.
authorTamar Christina <tamar.christina@arm.com>
Wed, 5 Jul 2017 12:04:07 +0000 (13:04 +0100)
committerCorinna Vinschen <corinna@vinschen.de>
Wed, 5 Jul 2017 12:41:27 +0000 (14:41 +0200)
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>
libgloss/arm/_kill.c
libgloss/arm/swi.h
libgloss/arm/syscalls.c

index 81354d47346314ebccdf1bb5de0d52e585bfbe5a..8871d3c367c353c318210c4308837be94f375815 100644 (file)
@@ -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
index b7fa243f86d32666a596da30aa671e1446cbebf1..72cb838dc9ae5e4141ac1af583f5e9b0fb18423c 100644 (file)
@@ -1,4 +1,5 @@
 #include "arm.h"
+#include <_ansi.h>
 
 /* SWI numbers for RDP (Demon) monitor.  */
 #define SWI_WriteC                 0x0
 
 
 /* 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__)
 
index 0ccad215cdb436cf3ff669038077e773bb35cbe7..80713680b33092cf2b4fa7a8ef8e972b989afec6 100644 (file)
@@ -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
This page took 0.041655 seconds and 5 git commands to generate.