📄 armsupp.c
字号:
ASSIGNV (AddOverflow (a, b, result));
}
/* Assigns the C flag after an subtraction of a and b to give result. */
void
ARMul_SubCarry (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNC ((NEG (a) && POS (b)) ||
(NEG (a) && POS (result)) || (POS (b) && POS (result)));
}
/* Assigns the V flag after an subtraction of a and b to give result. */
void
ARMul_SubOverflow (ARMul_State * state, ARMword a, ARMword b, ARMword result)
{
ASSIGNV (SubOverflow (a, b, result));
}
/* This function does the work of generating the addresses used in an
LDC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_LDC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_LDC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort*/
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_LDC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum))
{
printf
("SKYEYE ARMul_LDC,NOT ALLOW, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address))
INTERNALABORT (address);
cpab = (state->LDC[CPNum]) (state, ARMul_FIRST, instr, 0);
while (cpab == ARMul_BUSY)
{
ARMul_Icycles (state, 1, 0);
if (IntPending (state))
{
cpab = (state->LDC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
return;
}
else
cpab = (state->LDC[CPNum]) (state, ARMul_BUSY, instr, 0);
}
if (cpab == ARMul_CANT)
{
printf
("SKYEYE ARMul_LDC,NOT CAN, underinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
CPTAKEABORT;
return;
}
cpab = (state->LDC[CPNum]) (state, ARMul_TRANSFER, instr, 0);
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
while (cpab == ARMul_INC)
{
address += 4;
data = ARMul_LoadWordN (state, address);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_ldc_takeabort;
cpab = (state->LDC[CPNum]) (state, ARMul_DATA, instr, data);
}
//chy 2004-05-25
L_ldc_takeabort:
if (BIT (21))
{
if (!((state->abortSig || state->Aborted) && state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the work of generating the addresses used in an
STC instruction. The code here is always post-indexed, it's up to the
caller to get the input address correct and to handle base register
modification. It also handles the Busy-Waiting. */
void
ARMul_STC (ARMul_State * state, ARMword instr, ARMword address)
{
unsigned cpab;
ARMword data;
UNDEF_LSCPCBaseWb;
//printf("SKYEYE ARMul_STC, CPnum is %x, instr %x, addr %x\n",CPNum, instr, address);
/*chy 2004-05-23 should update this function in the future,should concern dataabort */
// skyeye_instr_debug=0;printf("SKYEYE debug end!!!!\n");
// chy 2004-05-25 , fix it now,so needn't printf
// printf("SKYEYE ARMul_STC, should update this function!!!!!\n");
//exit(-1);
if (!CP_ACCESS_ALLOWED (state, CPNum))
{
printf
("SKYEYE ARMul_STC,NOT ALLOW, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
ARMul_UndefInstr (state, instr);
return;
}
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
cpab = (state->STC[CPNum]) (state, ARMul_FIRST, instr, &data);
while (cpab == ARMul_BUSY)
{
ARMul_Icycles (state, 1, 0);
if (IntPending (state))
{
cpab = (state->STC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
return;
}
else
cpab = (state->STC[CPNum]) (state, ARMul_BUSY, instr, &data);
}
if (cpab == ARMul_CANT)
{
printf
("SKYEYE ARMul_STC,CANT, undefinstr, CPnum is %x, instr %x, addr %x\n",
CPNum, instr, address);
CPTAKEABORT;
return;
}
#ifndef MODE32
if (ADDREXCEPT (address) || VECTORACCESS (address))
INTERNALABORT (address);
#endif
BUSUSEDINCPCN;
//chy 2004-05-25
/*
if (BIT (21))
LSBase = state->Base;
*/
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
while (cpab == ARMul_INC)
{
address += 4;
cpab = (state->STC[CPNum]) (state, ARMul_DATA, instr, &data);
ARMul_StoreWordN (state, address, data);
//chy 2004-05-25
if (state->abortSig || state->Aborted)
goto L_stc_takeabort;
}
//chy 2004-05-25
L_stc_takeabort:
if (BIT (21))
{
if (!((state->abortSig || state->Aborted) && state->lateabtSig == LOW))
LSBase = state->Base;
}
if (state->abortSig || state->Aborted)
TAKEABORT;
}
/* This function does the Busy-Waiting for an MCR instruction. */
void
ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source)
{
unsigned cpab;
//printf("SKYEYE ARMul_MCR, CPnum is %x, source %x\n",CPNum, source);
if (!CP_ACCESS_ALLOWED (state, CPNum))
{
//chy 2004-07-19 should fix in the future ????!!!!
//printf("SKYEYE ARMul_MCR, ACCESS_not ALLOWed, UndefinedInstr CPnum is %x, source %x\n",CPNum, source);
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source);
while (cpab == ARMul_BUSY)
{
ARMul_Icycles (state, 1, 0);
if (IntPending (state))
{
cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
return;
}
else
cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source);
}
if (cpab == ARMul_CANT)
{
printf
("SKYEYE ARMul_MCR, CANT, UndefinedInstr CPnum is %x, source %x\n",
CPNum, source);
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
else
{
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
}
}
/* This function does the Busy-Waiting for an MRC instruction. */
ARMword
ARMul_MRC (ARMul_State * state, ARMword instr)
{
unsigned cpab;
ARMword result = 0;
//printf("SKYEYE ARMul_MRC, CPnum is %x, instr %x\n",CPNum, instr);
if (!CP_ACCESS_ALLOWED (state, CPNum))
{
//chy 2004-07-19 should fix in the future????!!!!
//printf("SKYEYE ARMul_MRC,NOT ALLOWed UndefInstr CPnum is %x, instr %x\n",CPNum, instr);
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->MRC[CPNum]) (state, ARMul_FIRST, instr, &result);
while (cpab == ARMul_BUSY)
{
ARMul_Icycles (state, 1, 0);
if (IntPending (state))
{
cpab = (state->MRC[CPNum]) (state, ARMul_INTERRUPT, instr, 0);
return (0);
}
else
cpab = (state->MRC[CPNum]) (state, ARMul_BUSY, instr, &result);
}
if (cpab == ARMul_CANT)
{
printf ("SKYEYE ARMul_MRC,CANT UndefInstr CPnum is %x, instr %x\n",
CPNum, instr);
ARMul_Abort (state, ARMul_UndefinedInstrV);
/* Parent will destroy the flags otherwise. */
result = ECC;
}
else
{
BUSUSEDINCPCN;
ARMul_Ccycles (state, 1, 0);
ARMul_Icycles (state, 1, 0);
}
return result;
}
/* This function does the Busy-Waiting for an CDP instruction. */
void
ARMul_CDP (ARMul_State * state, ARMword instr)
{
unsigned cpab;
if (!CP_ACCESS_ALLOWED (state, CPNum))
{
ARMul_UndefInstr (state, instr);
return;
}
cpab = (state->CDP[CPNum]) (state, ARMul_FIRST, instr);
while (cpab == ARMul_BUSY)
{
ARMul_Icycles (state, 1, 0);
if (IntPending (state))
{
cpab = (state->CDP[CPNum]) (state, ARMul_INTERRUPT, instr);
return;
}
else
cpab = (state->CDP[CPNum]) (state, ARMul_BUSY, instr);
}
if (cpab == ARMul_CANT)
ARMul_Abort (state, ARMul_UndefinedInstrV);
else
BUSUSEDN;
}
/* This function handles Undefined instructions, as CP isntruction. */
void
ARMul_UndefInstr (ARMul_State * state, ARMword instr ATTRIBUTE_UNUSED)
{
ARMul_Abort (state, ARMul_UndefinedInstrV);
}
/* Return TRUE if an interrupt is pending, FALSE otherwise. */
unsigned
IntPending (ARMul_State * state)
{
if (state->Exception)
{
/* Any exceptions. */
if (state->NresetSig == LOW)
{
ARMul_Abort (state, ARMul_ResetV);
return TRUE;
}
else if (!state->NfiqSig && !FFLAG)
{
ARMul_Abort (state, ARMul_FIQV);
return TRUE;
}
else if (!state->NirqSig && !IFLAG)
{
ARMul_Abort (state, ARMul_IRQV);
return TRUE;
}
}
return FALSE;
}
/* Align a word access to a non word boundary. */
ARMword
ARMul_Align (state, address, data)
ARMul_State *state ATTRIBUTE_UNUSED;
ARMword address;
ARMword data;
{
/* This code assumes the address is really unaligned,
as a shift by 32 is undefined in C. */
address = (address & 3) << 3; /* Get the word address. */
return ((data >> address) | (data << (32 - address))); /* rot right */
}
/* This routine is used to call another routine after a certain number of
cycles have been executed. The first parameter is the number of cycles
delay before the function is called, the second argument is a pointer
to the function. A delay of zero doesn't work, just call the function. */
void
ARMul_ScheduleEvent (ARMul_State * state, unsigned long delay,
unsigned (*what) (ARMul_State *))
{
unsigned long when;
struct EventNode *event;
if (state->EventSet++ == 0)
state->Now = ARMul_Time (state);
when = (state->Now + delay) % EVENTLISTSIZE;
event = (struct EventNode *) malloc (sizeof (struct EventNode));
if (!event)
{
printf ("SKYEYE:ARMul_ScheduleEvent: malloc event error\n");
exit (-1);
}
event->func = what;
event->next = *(state->EventPtr + when);
*(state->EventPtr + when) = event;
}
/* This routine is called at the beginning of
every cycle, to envoke scheduled events. */
void
ARMul_EnvokeEvent (ARMul_State * state)
{
static unsigned long then;
then = state->Now;
state->Now = ARMul_Time (state) % EVENTLISTSIZE;
if (then < state->Now)
/* Schedule events. */
EnvokeList (state, then, state->Now);
else if (then > state->Now)
{
/* Need to wrap around the list. */
EnvokeList (state, then, EVENTLISTSIZE - 1L);
EnvokeList (state, 0L, state->Now);
}
}
/* Envokes all the entries in a range. */
static void
EnvokeList (ARMul_State * state, unsigned long from, unsigned long to)
{
for (; from <= to; from++)
{
struct EventNode *anevent;
anevent = *(state->EventPtr + from);
while (anevent)
{
(anevent->func) (state);
state->EventSet--;
anevent = anevent->next;
}
*(state->EventPtr + from) = NULL;
}
}
/* This routine is returns the number of clock ticks since the last reset. */
unsigned long
ARMul_Time (ARMul_State * state)
{
return (state->NumScycles + state->NumNcycles +
state->NumIcycles + state->NumCcycles + state->NumFcycles);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -