| |
| #ifndef ARM_SEMIHOSTING_H_ |
| #define ARM_SEMIHOSTING_H_ |
| |
| // ---------------------------------------------------------------------------- |
| |
| // Semihosting operations. |
| enum OperationNumber |
| { |
| // Regular operations |
| SEMIHOSTING_EnterSVC = 0x17, |
| SEMIHOSTING_ReportException = 0x18, |
| SEMIHOSTING_SYS_CLOSE = 0x02, |
| SEMIHOSTING_SYS_CLOCK = 0x10, |
| SEMIHOSTING_SYS_ELAPSED = 0x30, |
| SEMIHOSTING_SYS_ERRNO = 0x13, |
| SEMIHOSTING_SYS_FLEN = 0x0C, |
| SEMIHOSTING_SYS_GET_CMDLINE = 0x15, |
| SEMIHOSTING_SYS_HEAPINFO = 0x16, |
| SEMIHOSTING_SYS_ISERROR = 0x08, |
| SEMIHOSTING_SYS_ISTTY = 0x09, |
| SEMIHOSTING_SYS_OPEN = 0x01, |
| SEMIHOSTING_SYS_READ = 0x06, |
| SEMIHOSTING_SYS_READC = 0x07, |
| SEMIHOSTING_SYS_REMOVE = 0x0E, |
| SEMIHOSTING_SYS_RENAME = 0x0F, |
| SEMIHOSTING_SYS_SEEK = 0x0A, |
| SEMIHOSTING_SYS_SYSTEM = 0x12, |
| SEMIHOSTING_SYS_TICKFREQ = 0x31, |
| SEMIHOSTING_SYS_TIME = 0x11, |
| SEMIHOSTING_SYS_TMPNAM = 0x0D, |
| SEMIHOSTING_SYS_WRITE = 0x05, |
| SEMIHOSTING_SYS_WRITEC = 0x03, |
| SEMIHOSTING_SYS_WRITE0 = 0x04, |
| |
| // Codes returned by SEMIHOSTING_ReportException |
| ADP_Stopped_ApplicationExit = ((2 << 16) + 38), |
| ADP_Stopped_RunTimeError = ((2 << 16) + 35), |
| |
| }; |
| |
| // ---------------------------------------------------------------------------- |
| |
| // SWI numbers and reason codes for RDI (Angel) monitors. |
| #define AngelSWI_ARM 0x123456 |
| #ifdef __thumb__ |
| #define AngelSWI 0xAB |
| #else |
| #define AngelSWI AngelSWI_ARM |
| #endif |
| // For thumb only architectures use the BKPT instruction instead of SWI. |
| #if defined(__ARM_ARCH_7M__) \ |
| || defined(__ARM_ARCH_7EM__) \ |
| || defined(__ARM_ARCH_6M__) \ |
| || defined(__ARM_ARCH_8M_BASE__) |
| #define AngelSWIInsn "bkpt" |
| #define AngelSWIAsm bkpt |
| #else |
| #define AngelSWIInsn "swi" |
| #define AngelSWIAsm swi |
| #endif |
| |
| #if defined(OS_DEBUG_SEMIHOSTING_FAULTS) |
| // Testing the local semihosting handler cannot use another BKPT, since this |
| // configuration cannot trigger HaedFault exceptions while the debugger is |
| // connected, so we use an illegal op code, that will trigger an |
| // UsageFault exception. |
| #define AngelSWITestFault "setend be" |
| #define AngelSWITestFaultOpCode (0xB658) |
| #endif |
| |
| static inline int |
| __attribute__ ((always_inline)) |
| call_host (int reason, void* arg) |
| { |
| int value; |
| asm volatile ( |
| |
| " mov r0, %[rsn] \n" |
| " mov r1, %[arg] \n" |
| #if defined(OS_DEBUG_SEMIHOSTING_FAULTS) |
| " " AngelSWITestFault " \n" |
| #else |
| " " AngelSWIInsn " %[swi] \n" |
| #endif |
| " mov %[val], r0" |
| |
| : [val] "=r" (value) /* Outputs */ |
| : [rsn] "r" (reason), [arg] "r" (arg), [swi] "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; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| // Function used in _exit() to return the status code as Angel exception. |
| static inline void |
| __attribute__ ((always_inline,noreturn)) |
| report_exception (int reason) |
| { |
| call_host (SEMIHOSTING_ReportException, (void*) reason); |
| |
| for (;;) |
| ; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| |
| #endif // ARM_SEMIHOSTING_H_ |