98 Semihosting(TCpuAccessor &cpua, TBus bus) : bus_(bus), cpua_(cpua) {}
103 auto r1 = cpua_.template ReadRegister<RegisterId::kR1>();
104 auto mem = MemoryHelpers::ReadMemory(cpua_, bus_, r1, r1 + 0x4, r1 + 0x8);
109 auto r1 = cpua_.template ReadRegister<RegisterId::kR1>();
110 auto mem = MemoryHelpers::ReadMemory(cpua_, bus_, r1, r1 + 0x4);
115 auto r1 = cpua_.template ReadRegister<RegisterId::kR1>();
116 auto mem = MemoryHelpers::ReadMemory(cpua_, bus_, r1);
122 BkptFlagsSet bkpt_flags;
127 BkptFlagsSet bkpt_flags = 0U;
128 bkpt_flags |=
static_cast<BkptFlagsSet
>(BkptFlags::kOmitException);
132 LOG_DEBUG(TLogger,
"kSysHeapInfo(0x%0x)", r0);
139 TRY_ASSIGN(mem3, SemihostResult, ReadR1Words<3>());
140 const auto &ptr = mem3[0];
141 const auto &mode = mem3[1];
142 const auto &w_len = mem3[2];
144 char buf[kBufferLen];
146 MemoryHelpers::CpyFromEmuMem(cpua_, bus_, buf,
sizeof(buf) - 1, ptr, w_len);
148 LOG_DEBUG(TLogger,
"kSysOpen(0x%0x) - 0x%0x 0x%0x 0x%0x - '%s'", r0, ptr, mode, w_len, buf);
150 if (strcmp(buf,
":tt") == 0) {
151 if ((mode >= 0U) && (mode <= 3U)) {
152 result = kHandleStdin;
153 }
else if ((mode >= 4U) && (mode <= 7U)) {
154 result = kHandleStdout;
155 }
else if ((mode >= 8U) && (mode <= 11U)) {
156 result = kHandleStderr;
160 }
else if (strcmp(buf,
":semihosting-features") == 0) {
161 result = kHandleSemihostFeatures;
171 const auto &fhandle = mem3[0];
172 const auto &ptr = mem3[1];
173 const auto &w_len = mem3[2];
175 if ((fhandle != kHandleStdout) && (fhandle != kHandleStderr)) {
179 char buf[kBufferLen];
182 MemoryHelpers::CpyFromEmuMem(cpua_, bus_, buf,
sizeof(buf) - 1, ptr, w_len));
185 LOG_TRACE(TLogger,
"kSysWrite(0x%0x)- 0x%0x 0x%0x 0x%0x", r0, fhandle, ptr, w_len, buf);
186 LOG_INFO(TLogger,
"stdout << '%s'", buf);
195 const auto &fhandle = mem3[0];
196 const auto &ptr = mem3[1];
197 const auto &r_len = mem3[2];
199 LOG_DEBUG(TLogger,
"kSysRead(0x%0x)- 0x%0x 0x%0x 0x%0x", r0, fhandle, ptr, r_len);
201 if (fhandle == kHandleSemihostFeatures) {
203 auto *feature_data = &kFeatureData[semihost_features_position_];
204 auto features_data_size =
sizeof(kFeatureData) - semihost_features_position_;
208 MemoryHelpers::CpyToEmuMem(cpua_, bus_, ptr, r_len, feature_data, features_data_size));
210 semihost_features_position_ += read_bytes;
220 const auto &fhandle = mem1[0];
222 LOG_DEBUG(TLogger,
"kSysIsTTY(0x%0x) - 0x%0x", r0, fhandle);
224 if (fhandle != kHandleStdout) {
235 const auto &fhandle = mem1[0];
236 LOG_DEBUG(TLogger,
"kSysFLen(0x%0x) - 0x%0x", r0, fhandle);
238 if ((fhandle == kHandleStdin) || (fhandle == kHandleStdout) || (fhandle == kHandleStderr)) {
242 if (fhandle == kHandleSemihostFeatures) {
243#ifdef _DISABLE_EXT_EXIT
246 sh_ret =
sizeof(kFeatureData);
255 const auto &fhandle = mem2[0];
256 const auto &fpos = mem2[1];
257 LOG_DEBUG(TLogger,
"kSysSeek(0x%0x) - 0x%0x - %u", r0, fhandle, fpos);
259 if (fhandle == kHandleSemihostFeatures) {
260 if (fpos <
sizeof(kFeatureData)) {
261 semihost_features_position_ = fpos;
274 LOG_ERROR(TLogger,
"kSysErrNo(0x%0x)", r0);
279 auto reason_code = cpua_.template ReadRegister<RegisterId::kR1>();
280 if (reason_code != 0x0) {
285 LOG_DEBUG(TLogger,
"kSysClock(0x%0x) - host_clock:%u, CLOCKS_PER_SEC:%u", r0,
286 static_cast<unsigned int>(ticks),
static_cast<unsigned int>(CLOCKS_PER_SEC));
288 uint64_t ticks_64 =
static_cast<u64
>(ticks);
290 uint64_t centiseconds = (ticks_64 * 100) / CLOCKS_PER_SEC;
292 sh_ret =
static_cast<i32
>(centiseconds);
297 LOG_INFO(TLogger,
"kSysExit(0x%0x)", r0);
299 auto reason_code = cpua_.template ReadRegister<RegisterId::kR1>();
301 if (reason_code ==
static_cast<u32
>(ReasonCodes::kADPStoppedApplicationExit)) {
302 bkpt_flags |=
static_cast<BkptFlagsSet
>(BkptFlags::kRequestExit);
304 bkpt_flags |=
static_cast<BkptFlagsSet
>(BkptFlags::kRequestErrorExit);
309 case kSysExitExtended: {
311 const auto &reason_code = mem2[0];
312 const auto &reason_subcode = mem2[1];
313 LOG_INFO(TLogger,
"kSysExitExtended(0x%0x) - reason_code: 0x%x - reason_subcode: 0x%x", r0,
314 reason_code, reason_subcode);
315 status_code_ = reason_subcode;
316 if (reason_code ==
static_cast<u32
>(ReasonCodes::kADPStoppedApplicationExit)) {
317 bkpt_flags |=
static_cast<BkptFlagsSet
>(BkptFlags::kRequestExit);
319 bkpt_flags |=
static_cast<BkptFlagsSet
>(BkptFlags::kRequestErrorExit);
324 case kSysGetCmdLine: {
327 const auto &w1 = mem2[0];
328 const auto &w2 = mem2[1];
329 static_cast<void>(w1);
330 static_cast<void>(w2);
331 LOG_DEBUG(TLogger,
"kSysGetCmdLine(0x%0x) - 0x%0x 0x%0x", r0, w1, w2);
338 const auto &fhandle = mem1[0];
340 if ((fhandle != kHandleStdin) && (fhandle != kHandleStdout) && (fhandle != kHandleStderr) &&
341 (fhandle != kHandleSemihostFeatures)) {
344 LOG_DEBUG(TLogger,
"kSysClose(0x%0x) - 0x%0x", r0, fhandle);
350 LOG_ERROR(TLogger,
"Unknown(0x%0x)", r0);
360 virtual Result<BkptFlagsSet> Call(
const uint32_t &imm32)
override {
361 if (imm32 != 0xabu) {
364 auto r0 = cpua_.template ReadRegister<RegisterId::kR0>();
366 cpua_.WriteRegister(RegisterId::kR0, sh_res.ret_r0);
368 return Ok(sh_res.bkpt_flags);
371 virtual uint32_t GetExitStatusCode()
const override {
return status_code_; }
374 static constexpr u32 kBufferLen = 128U;
379 i32 status_code_{0U};
380 u32 semihost_features_position_{0U};