📄 validate.c
字号:
/* validate.c - ARM validation suite co-processxor and OS. )
*
* Copyright (C) Advanced RISC Machines Limited, 1995-1998 .
* Copyright (C) 1998-2001 ARM Limited.
* All rights reserved.
*
* RCS $Revision: 1.3.4.10.2.3 $
* Checkin $Date: 2003/07/10 15:34:20 $
* Revising $Author: dsinclai $
*/
#include "minperip.h"
#include "armul_cnf.h"
#ifndef NDEBUG
# if 1
# else
# define VERBOSE
# endif
#endif
#define ARMSignal_IRQ RDIPropID_ARMSignal_IRQ
#define ARMSignal_FIQ RDIPropID_ARMSignal_FIQ
/* Deprecated - no longer used in V6. */
#define ARMSignal_SE RDIPropID_ARMSignal_SE
#ifndef BITS
# define BITS(m,n) ( (ARMword)(instr<<(31-(n))) >> ((31-(n))+(m)) )
#endif
#ifndef BIT
# define BIT(n) ( (instr >> n) & 1 )
#endif
typedef RDI_Error ARMul_Error;
/* Software model of the Validation Suite Coprocessors. Eight */
/* Coprocessors are defined in the "CPU Validation Test Bench" */
/* ARM-100-0019-A01. Of these all but CP_PRIVELEGED is supported */
/* ARM7 based models use memory cycle based event scheduling, */
/* and ARM9 and ARM10 based models use core cycle timings. */
/* Coprocessor names */
#define CP_BOUNCE_D 0
#define CP_BUSYWAIT_D 1
#define CP_BOUNCE_E 2
#define CP_BUSYWAIT_E 3
#define CP_BUSYWAIT 4
#define CP_TRICKBOX 5
#define CP_PRIVELEGED 6
#define CP_STANDARD 7
#define CP_DTL 8
/* Default Busy_wait count for CP_BUSYWAIT */
#define CP1_WAIT_COUNT 1
#define CP2_WAIT_COUNT 1
#define CP3_WAIT_COUNT 2
#define CP4_WAIT_COUNT 1
#define CP5_WAIT_COUNT 0
typedef struct {
ARMTime ulBusyWaitStart;
int iBusyWaitDuration;
int iBusyWaiting;
} CPBusyWait;
BEGIN_STATE_DECL(Validate)
CPBusyWait CP1Busy /* ={0l,0, FALSE} */;
CPBusyWait CP2Busy /* ={0l,0, FALSE} */;
CPBusyWait CP3Busy /* ={0l,0, FALSE} */;
CPBusyWait CP4Busy /* ={0l,0, FALSE} */;
CPBusyWait CP5Busy /*={0l,0, FALSE} */;
CPBusyWait CP7Busy /*={0l,0, FALSE} */;
CPBusyWait CP8Busy /*={0l,0, FALSE} */;
/* All Coprocessors apart from 0 (no registers) and 5 share a common set of registers */
ARMword ValCPStandardReg[16];
#define ValCP1Reg state->ValCPStandardReg
#define ValCP3Reg state->ValCPStandardReg
#define ValCP4Reg state->ValCPStandardReg
#define ValCP7Reg state->ValCPStandardReg
#define ValCP8Reg state->ValCPStandardReg
ARMword ValCP5Reg[16];
unsigned ValCP5_LDCL_Words;
int ldc_regNum;
unsigned ldc_words;
unsigned ldc_wordsToGet;
int stc_regNum;
unsigned stc_words;
unsigned stc_wordsToSend;
bool bARM9_CoproIF, bARM9_Extensions;
unsigned vs_CoproIFType;
ARMTime FRTimer;
#ifdef NotYet
ARMul_SchedulerMethod schedule;
#endif
int CP8_BounceNext;
unsigned vcp_InterfaceDelay; /* 3 core cycles for ARM9 */
/* ARMul_SchedulerMethod schedule; */
ARMTime CPBusyUntil[16];
END_STATE_DECL(Validate)
static void DoASE(void *handle);
static void DoAFIQ(void *handle);
static void DoAIRQ(void *handle);
static void DoAReset (void *handle);
static void Validate_ScheduleUnretractable(RDI_ModuleDesc *mdesc,
ARMul_TimedCallBackProc *func,
ValidateState *state,
ARMTime when,
ARMTime atc_period)
{
void *fhandle = state;
assert(mdesc == &state->coredesc);
assert(0 == atc_period);
when += state->vcp_InterfaceDelay; /* NEEDED FOR ARM926 */
(void)ARMulif_ScheduleNewTimedCallback_CoreCycles(
mdesc, func, fhandle, when, atc_period);
}
/* Check whether the Coprocessor returned ARMul_LAST */
/* and return ARMul_INC instead for non ARM9 based */
/* models. */
static unsigned CheckLast(void *handle, int result)
{
ValidateState *state=(ValidateState *)handle;
if ((result == ARMul_CP_LAST) && !state->bARM9_CoproIF) {
return ARMul_CP_INC;
}
else {
return result;
}
}
/* Determine the correct number of busy cycles for the */
/* Core - ARM9xxE cores always have one extra on external */
/* Coprocessor operations. */
static unsigned long CheckBusyCycles(void *handle, unsigned long busy_cycles)
{
ValidateState *state=(ValidateState *)handle;
if (state->bARM9_CoproIF && state->bARM9_Extensions)
/* was (ARMul_Properties(state) & ARM_ARM9Extensions)*/ {
/* ARM9xxES Core */
return busy_cycles + 1;
}
else {
return busy_cycles;
}
}
/* Checks whether the copro is waiting for a previous instruction */
/* to complete and also whether there is an interrupt. */
static bool CheckBusyWait(unsigned type, CPBusyWait *CPBusy,
unsigned long busy_cycles,
ARMTime cycle_count, int *result)
{
ARMTime finish;
/* If we get an interrupt, regardless of busy wait status then exit */
if (type == ARMul_CP_INTERRUPT) {
CPBusy->iBusyWaiting = FALSE; /* Clear busy waiting flag */
*result = ARMul_CP_DONE; /* We've been interrupted */
return TRUE;
}
/* Is this CP currently busy waiting? */
if (CPBusy->iBusyWaiting) {
/* Yes it might be, check times */
finish = CPBusy->ulBusyWaitStart + CPBusy->iBusyWaitDuration;
if( cycle_count < finish ) {
/* Yes it is busy waiting still, so return ARMul_CP_BUSY*/
*result = ARMul_CP_BUSY;
return TRUE;
}
else {
/* Assert that we aren't busy waiting any more */
CPBusy->iBusyWaiting = FALSE;
*result = ARMul_CP_FIRST;
}
}
else if (type == ARMul_CP_FIRST) {
/* Start a new Busy Wait */
CPBusy->iBusyWaiting = TRUE;
CPBusy->ulBusyWaitStart = cycle_count;
CPBusy->iBusyWaitDuration = busy_cycles;
*result = ARMul_CP_BUSY;
return TRUE;
}
return FALSE;
}
/* Code to get the current cycle count total, either */
/* core cycle type armulators (ARM9) or others.
*
* Since we are a coprocessor, we'd actually like to use
* the number of clocks on the coprocessor-bus.
* NB This coprocessor requires that CoreCycles advances while
* the core is busy-waited by a coprocessor.
*/
static ARMTime GetCycleCount(ValidateState *state)
{
/* ValidateState *state=(ValidateState *)handle; */
#ifdef OldCode
/* This doesn't work for ARMISS, which doesn't emit bus-cyles
* while waiting for a coprocessor. */
return ARMulif_Time(&state->coredesc);
#else
/* ARMulif_CpuCycles causes ARM7TDMI..ARM740T to fail test TD1-32 */
ARMTime t = ARMulif_CoreCycles(&state->coredesc);
/* return ( t > 0 ) ? t : ARMulif_Time(&state->coredesc); */
assert(t != 0 && t != (ARMTime)-1);
return t;
#endif
}
/* Bouncing Coprocessors (CP0 and CP2) */
static int CP0CDP(void *handle, int type, ARMword instr, ARMword *dummy)
{
UNUSEDARG(handle); UNUSEDARG(type);
UNUSEDARG(instr); (void)dummy;
return ARMul_CP_CANT;
}
static int CP0LDCMCR(void *handle, int type, ARMword instr, ARMword *data)
{
UNUSEDARG(handle);
UNUSEDARG(type);
UNUSEDARG(instr);
UNUSEDARG(data);
return ARMul_CP_CANT;
}
static int CP0STCMRC(void *handle, int type, ARMword instr, ARMword *data)
{
UNUSEDARG(handle);
UNUSEDARG(type);
UNUSEDARG(instr);
UNUSEDARG(data);
return ARMul_CP_CANT;
}
static int CP2CDP(void *handle, int type, ARMword instr, ARMword *dummy)
{
ValidateState *state=(ValidateState *)handle;
ARMTime cycle_count = GetCycleCount(state);
int result;
(void)instr;
(void)dummy;
if (CP2_WAIT_COUNT && CheckBusyWait(type, &state->CP2Busy, CP4_WAIT_COUNT, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
return ARMul_CP_CANT;
}
static int CP2LDCMCR(void *handle, int type, ARMword instr, ARMword *data)
{
ValidateState *state=(ValidateState *)handle;
ARMTime cycle_count = GetCycleCount(state);
int result;
(void)instr;
(void)data;
if (CP2_WAIT_COUNT && CheckBusyWait(type, &state->CP2Busy, CP4_WAIT_COUNT, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
return ARMul_CP_CANT;
}
static int CP2STCMRC(void *handle, int type, ARMword instr, ARMword *data)
{
ValidateState *state=(ValidateState *)handle;
ARMTime cycle_count = GetCycleCount(state);
int result;
(void)instr;
(void)data;
if (CP2_WAIT_COUNT && CheckBusyWait(type, &state->CP2Busy, CP4_WAIT_COUNT, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
return ARMul_CP_CANT;
}
static int DoCP4LDC(void *handle, int type, ARMword instr,ARMword data, unsigned long busy_cycles, ARMTime cycle_count)
{
ValidateState *state=(ValidateState *)handle;
static int regNum;
static unsigned words;
static unsigned wordsToGet;
int result = type;
if (busy_cycles && CheckBusyWait(type, &state->CP4Busy, busy_cycles, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
wordsToGet = BIT(22) ? 4 : 1;
if (type == ARMul_CP_FIRST || result == ARMul_CP_FIRST) {
regNum = BITS(12,15); /* Get the register number */
words = 0; /* Reset the word fetch counter */
if (wordsToGet == 1) {
return ARMul_CP_LAST;
}
else {
return ARMul_CP_INC;
}
}
if (type == ARMul_CP_TRANSFER) {
if (wordsToGet == 1) {
return ARMul_CP_LAST;
}
else {
return ARMul_CP_INC;
}
}
if (BIT(22)) {
/* Its a CPDTL instruction so 4 words to fetch */
/* Do the data access, incrementing the register as we go */
ValCP4Reg[regNum++] = data;
regNum &= 0xf;
/* If we've got enough words then return done, else request more ! */
words++;
if (words >= wordsToGet) {
return ARMul_CP_DONE;
}
else if ((words+1) == wordsToGet) {
return ARMul_CP_LAST;
}
else {
return ARMul_CP_INC;
}
}
else {
/* NOT a long access so get just one word */
ValCP4Reg[BITS(12,15)] = data;
return ARMul_CP_DONE;
}
}
static int CP4LDC(void *handle, int type, ARMword instr, ARMword *data)
{
ValidateState *state=(ValidateState *)handle;
ARMTime cycle_count = GetCycleCount(state);
return CheckLast(handle, DoCP4LDC(handle, type, instr, data ? *data : 0, CheckBusyCycles(handle, CP4_WAIT_COUNT), cycle_count));
}
static int DoCP4STC(void *handle, int type, ARMword instr,
ARMword *data, unsigned long busy_cycles, ARMTime cycle_count)
{
ValidateState *state=(ValidateState *)handle;
static int regNum;
static unsigned words;
static unsigned wordsToSend;
int result = type;
if (busy_cycles && CheckBusyWait(type, &state->CP4Busy, busy_cycles, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
if (type == ARMul_CP_FIRST || result == ARMul_CP_FIRST) {
regNum = BITS(12,15); /* Get the register number */
words = 0; /* Reset the word fetch counter */
wordsToSend = 1; /* just to be safe */
return ARMul_CP_INC;
}
if (BIT(22)) {
/* it's a long access*/
/* Do we want 2 or 4 words transferred? */
/* Its a CPDTL instruction so 4 words */
wordsToSend = 4;
/* Now do the data access */
*data = ValCP4Reg[regNum++];
/* Store the data in Register[regNum] and increment regNum for the
next transfer */
/* If we've got enough words then return done, else request more ! */
if (++words >= wordsToSend)
return ARMul_CP_DONE;
else
return ARMul_CP_INC;
}
else {
/* get just one word */
*data = ValCP4Reg[regNum];
return ARMul_CP_DONE;
}
}
static int CP4STC(void *handle, int type,
ARMword instr, ARMword *data)
{
ValidateState *state=(ValidateState *)handle;
ARMTime cycle_count = GetCycleCount(state);
int result = CheckLast(handle, DoCP4STC(handle, type, instr, data, CheckBusyCycles(handle, CP4_WAIT_COUNT),
cycle_count));
return result;
}
/* CP5 LDC instruction. Does 2 word accesses */
static unsigned DoCP5LDC(void *handle, unsigned type, ARMword instr, ARMword data, unsigned long busy_cycles, ARMTime cycle_count)
{
ValidateState *state=(ValidateState *)handle;
static int regNum;
static unsigned words;
static unsigned wordsToGet;
int result = type;
if (busy_cycles && CheckBusyWait(type, &state->CP5Busy, busy_cycles, cycle_count, &result)) {
return result; /* Either busy waiting or interrupted */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -