📄 semihost.c
字号:
/* for semihostingstate */
#define SEMIHOSTSTATE_ENABLED 1
/* Returns the time in bus-clocks. */
static ARMTime Semihost_GetTime(OSState *osstate)
{
return ARMulif_Time(&osstate->coredesc);
}
static void LOG_FILE_OP(OSState *state, char *fmt, ...)
{
if (state->os_file_log)
{
va_list ap;
char buf[1000];
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
fputs(buf,state->os_file_log);
va_end(ap);
}
}
static bool_int isNewLine(char c)
{
return c == '\n' || c == '\r' || c == '\0';
}
static void PutInLineBuffer(OSState *os, char *txt)
{
while (txt && *txt)
{
if (isNewLine(*txt))
{
if (os->nchars_in_linebuf)
{
os->linebuf[os->nchars_in_linebuf] = '\0';
/* Trace it, compare it, or whatever */
if (os->os_Trace_OutPut && os->os_TracerPrintf.func)
{
os->os_TracerPrintf.func(os->os_TracerPrintf.handle,
"[SEMIHOST]");
os->os_TracerPrintf.func(os->os_TracerPrintf.handle,
"%s\n", os->linebuf);
}
}
os->nchars_in_linebuf = 0;
}
else if (os->nchars_in_linebuf < LINE_LENGTH - 1)
{
os->linebuf[os->nchars_in_linebuf++] = *txt;
}
++txt;
}
}
/* Return microseconds of wall-clock-time
*/
static ARMword wallclock_millisecs(OSState *osstate)
{
(void)osstate;
#ifdef CLOCKS_PER_SEC
# if (CLOCKS_PER_SEC != 1000000) && (CLOCKS_PER_SEC != 1000)
# error "CLOCKS_PER_SEC unexpected value"
# endif
#endif
return (ARMword)(clock() / (CLOCKS_PER_SEC/1000));
}
/* for SYS_READ_CORECYCLES_AND_INSTRS */
static void read_core_cycles_and_instrs(OSState *osstate)
{
RDI_CycleDesc *descs;
ARMword *counters;
ARMword ii;
ARMword ndesc=0;
ARMword cycs_lo=0, insts_lo=0;
ARMword cycs_hi=0, insts_hi=0;
/* Fill in ndesc with the number of counters in the model */
osstate->coredesc.rdi->info(osstate->coredesc.handle, RDIRequestCyclesDesc, &ndesc, NULL);
/* Allocate some space (note that counters take up two words each) */
descs=(RDI_CycleDesc *)calloc(ndesc,sizeof(RDI_CycleDesc));
counters=(ARMword *)calloc((ndesc+1)*2, sizeof(ARMword));
/* Fetch the info */
osstate->coredesc.rdi->info(osstate->coredesc.handle, RDIRequestCyclesDesc, &ndesc, (ARMword *)descs);
osstate->coredesc.rdi->info(osstate->coredesc.handle, RDICycles, counters, NULL);
for (ii=0 ; ii<ndesc ; ii++) {
/* Search for likely cycle counts first */
if (!strcmp(descs[ii].name + 1, "Core_Cycles")) {
cycs_lo=counters[ii*2+1];
cycs_hi=counters[ii*2];
}
/* And then instruction counts.. */
if (!strcmp(descs[ii].name + 1, "Instructions")) {
insts_lo=counters[ii*2+1];
insts_hi=counters[ii*2];
}
}
free(descs);
free(counters);
{
ARMword mode = ARMulif_GetCPSR(&osstate->coredesc) & 0x1f ;
ARMword arg_addr = ARMulif_GetReg(&osstate->coredesc,mode,1);
ARMulif_WriteWord(&osstate->coredesc, arg_addr, cycs_hi);
ARMulif_WriteWord(&osstate->coredesc, arg_addr+4, cycs_lo);
ARMulif_WriteWord(&osstate->coredesc, arg_addr+8, insts_hi);
ARMulif_WriteWord(&osstate->coredesc, arg_addr+12, insts_lo);
}
#ifdef VERBOSE
Hostif_ConsolePrint(osstate->hostif,
"read_core_cycles_and_instrs ndec:%u ->%u, %u\n",
(unsigned)ndesc,
(unsigned)cycs_lo, (unsigned)insts_lo);
#endif
}
static bool GetString(RDI_ModuleDesc *coredesc, ARMword from, char *to,
unsigned int BufferSize);
static bool PutString(RDI_ModuleDesc *coredesc, ARMword dest_addr,
char const *source,
unsigned int BufferSize)
{
unsigned int i = 0;
do {
if (++i > BufferSize)
{
return FALSE;
}
ARMulif_WriteByte(coredesc, dest_addr++, *source);
} while (*source++ != '\0');
return TRUE;
}
/* Args are r1: dest buffer address
* r2: size of buffer
* r3: address of tag.
*/
static void sys_lookup_config(OSState *my)
{
ARMword mode = ARMulif_GetCPSR(&my->coredesc) & 0x1f ;
ARMword dest_addr = ARMulif_GetReg(&my->coredesc,mode,1);
ARMword dest_size = ARMulif_GetReg(&my->coredesc,mode,2);
ARMword tag_addr = ARMulif_GetReg(&my->coredesc,mode,3);
char tag[129];
ARMword r0 = (ARMword)-1;
if (GetString(&my->coredesc, tag_addr, tag, 128))
{
char const *option = ToolConf_Lookup(my->config, (tag_t)tag);
if (option != NULL)
{
if (PutString(&my->coredesc, dest_addr, option, dest_size))
{
/* Claim success */
r0 = 0;
}
}
}
ARMulif_SetReg(&my->coredesc, mode, 0, r0);
}
/* Return centiseconds of real or emulated time.
* Real time is from the host's clock(),
* Emulated time is
* coreclocks * centiSecondsPerSecond [cs*Hz] / coreClockRate[Hz]
*
*/
static ARMTime OS_GetCentiseconds(OSState *osstate)
{
/* First see if the core supports RDIRead_Clock */
ARMword secs,ns;
if (osstate->os_bUseRealTime)
{
return
#ifdef CLOCKS_PER_SEC
( (CLOCKS_PER_SEC >= 100)
? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
: (ARMword) ((clock() * 100) / CLOCKS_PER_SEC)
)
#else
/* Assume unix... clock() returns microseconds */
(ARMword) (clock() / 10000)
#endif
;
}
else if (osstate->coredesc.rdi->info(osstate->coredesc.handle,
RDIRead_Clock,&ns,&secs) == RDIError_NoError)
{
ARMTime t = (ARMTime)secs * 100 + (ns / 10000) / 1000;
#ifdef VERBOSE_GetCS
printf("GetCS secs:%lu ns:%lu -> %lu\n",
(unsigned long)secs,(unsigned long)ns, (unsigned long)t);
#endif
return t;
}
else
{
assert(osstate->os_BusSpeed != 0);
return (ARMword)(ARMulif_Time(&osstate->coredesc) * 100 /
osstate->os_BusSpeed);
}
}
/* Leaf node - no need to call next->func. */
static unsigned Time_Access(GenericAccessCallback *gacb,
ARMword address,
ARMword *data,
unsigned access_type)
{
OSState *osstate = (OSState *)gacb->handle;
(void)address;
#if 0
printf("Time_Access type:0x%04x", access_type);
#endif
switch (access_type & (ACCESS_WRITE | 0xF))
{
case (ACCESS_READ | ACCESS_WORD):
*data = (uint32)Semihost_GetTime(osstate);
return RDIError_NoError;
#ifdef TIME_CAN_BE_SET
case (ACCESS_WRITE | ACCESS_WORD): {
ARMTime ti = ARMulif_Time(&osstate->coredesc);
ti = ( ti & ((ARMTime)0xFFFFFFFFU << 32) ) | (ARMTime)*data;
return ARMulif_SetTime(&osstate->coredesc, ti);
}
#endif
}
return RDIError_NoSuchHandle;
}
#ifdef CPUTIME_HI
/* Leaf node - no need to call next->func. */
static unsigned Time_Access_Hi(GenericAccessCallback *gacb,
ARMword address,
ARMword *data,
unsigned access_type)
{
OSState *osstate = (OSState *)gacb->handle;
(void)address;
switch (access_type & (ACCESS_WRITE | 0xF))
{
case (ACCESS_READ | ACCESS_WORD):
*data = (uint32)(Semihost_GetTime(osstate) >> 32);
return RDIError_NoError;
}
return RDIError_NoSuchHandle;
}
#endif
static unsigned Clock_Access(GenericAccessCallback *gacb,
ARMword address,
ARMword *data,
unsigned access_type)
{
OSState *osstate = (OSState *)gacb->handle;
(void)address;
switch (access_type & (ACCESS_WRITE | 0xF))
{
case (ACCESS_READ | ACCESS_WORD):
*data = (uint32)OS_GetCentiseconds(osstate);
return RDIError_NoError;
}
return RDIError_NoSuchHandle;
}
static ARMul_RDIPropertyDesc Time_PropDesc =
{
/* */
{
"cputime", /* name */
"Time in units of core CPUSPEED", /* description */
0, /* ID */
FALSE, /* AsString */
0, /* maxStrLen */
TRUE, /* AsNumeric */
FALSE, /* IsSigned */
32, /* Width */
FALSE, /* readOnly */
FALSE, /* monotonicIncreasing */
FALSE, /* traceable */
RDIProperty_PDT_Standard
},
{
NULL,
Time_Access,
NULL
}
};
#ifdef CPUTIME_HI
static ARMul_RDIPropertyDesc TimeHi_PropDesc =
{
{
"cputime_hi", /* name */
"Time in units of core CPUSPEED", /* description */
0, /* ID */
FALSE, /* AsString */
0, /* maxStrLen */
TRUE, /* AsNumeric */
FALSE, /* IsSigned */
32, /* Width */
TRUE, /* readOnly */
FALSE, /* monotonicIncreasing */
FALSE, /* traceable */
RDIProperty_PDT_Standard
},
{
NULL,
Time_Access_Hi,
NULL
}
};
#endif
static ARMul_RDIPropertyDesc Clock_PropDesc =
{
/* */
{
"sys_clock", /* name */
"Time in centiseconds as read by semihosting SYS_CLOCK", /* description */
0, /* ID */
FALSE, /* AsString */
0, /* maxStrLen */
TRUE, /* AsNumeric */
FALSE, /* IsSigned */
32, /* Width */
TRUE, /* readOnly */
FALSE, /* monotonicIncreasing */
FALSE, /* traceable */
RDIProperty_PDT_Standard
},
{
NULL,
Clock_Access,
NULL
}
};
/* fileflags */
#define NOOP 0
#define BINARY 1
#define READOP 2
#define WRITEOP 4
RDI150_OpenAgentProc OS_Init;
RDI150_CloseAgentProc OS_Exit;
static unsigned Angel_ConfigEvents(void *handle, void *data);
static SimRdiRegistrationListener OS_SimRdiListener;
BEGIN_INIT(OS)
{ ARMword i ;
OSState *osstate = (OSState *)state;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -