1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#include "arm.h"
#include <_ansi.h>
/* SWI numbers for RDP (Demon) monitor. */
#define SWI_WriteC 0x0
#define SWI_Write0 0x2
#define SWI_ReadC 0x4
#define SWI_CLI 0x5
#define SWI_GetEnv 0x10
#define SWI_Exit 0x11
#define SWI_EnterOS 0x16
#define SWI_GetErrno 0x60
#define SWI_Clock 0x61
#define SWI_Time 0x63
#define SWI_Remove 0x64
#define SWI_Rename 0x65
#define SWI_Open 0x66
#define SWI_Close 0x68
#define SWI_Write 0x69
#define SWI_Read 0x6a
#define SWI_Seek 0x6b
#define SWI_Flen 0x6c
#define SWI_IsTTY 0x6e
#define SWI_TmpNam 0x6f
#define SWI_InstallHandler 0x70
#define SWI_GenerateError 0x71
/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
#if defined (SEMIHOST_V2) \
&& defined (SEMIHOST_V2_MIXED_MODE) \
&& !defined (THUMB_VXM)
#define AngelSWI_ARM 0xE10F0070 /* HLT #0xF000 A32. */
#ifdef __thumb__
#define AngelSWI 0xBABC /* HLT #0x3c 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(IMM) bkpt IMM
#elif defined (SEMIHOST_V2) && defined (SEMIHOST_V2_MIXED_MODE)
/* This is actually encoding the HLT instruction, however we don't have
support for this in older assemblers. So we have to encode the
instruction manually. */
#define AngelSWIInsn ".inst"
#define AngelSWIAsm(IMM) .inst IMM
#else
#define AngelSWIInsn "swi"
#define AngelSWIAsm(IMM) swi IMM
#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_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 (char*, int, int);
extern int _has_ext_exit_extended (void);
extern int _has_ext_stdout_stderr (void);
#endif
#if defined(ARM_RDI_MONITOR) && !defined(__ASSEMBLER__)
static inline int
do_AngelSWI (int reason, void * arg)
{
int value;
asm volatile ("mov r0, %1; mov r1, %2; " AngelSWIInsn " %a3; mov %0, r0"
: "=r" (value) /* Outputs */
: "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
/* Clobbers r0 and r1, and lr if in supervisor mode */);
/* Accordingly to page 13-77 of ARM DUI 0040D other registers
can also be clobbered. Some memory positions may also be
changed by a system call, so they should not be kept in
registers. Note: we are assuming the manual is right and
Angel is respecting the APCS. */
return value;
}
#endif
|