📄 uniregs_registration_event.h
字号:
/* the maximum number of blocks that SimRdi_Manager can cope with is this
number, any higher and you need to recompile SimRdi_Manager. */
uniregs_armulator_top = NUMBER_OF_UNIREGS_BLOCKS-1
};
/*
* UniregsRegistration
*
* This is the object that gets broadcast in the RegistrationEvent.
*/
/* typedef struct tag_uniregistration UniregsRegistration; // in
// simrdi_registration_event.h */
struct tag_uniregsregistration {
uint32 signature; /* should check == UNIREGS_REGISTRATION_SIGNATURE */
struct {
uint32 major;
uint32 minor;
} version; /* these are the version numbers of SimRdi_Manager */
void* handle; /* handle for the private data of the methods */
int number; /* number of members below this one */
void (*advertise)( UniregsRegistration* handle,
Uniregs_Advert* advert );
}; /* UniregsRegistration */
/*
* Useful constructions for coprocessors
*/
#define DEBUG_MRC_OPCODE(opcode1,crn,rd,cp_num,opcode2,crm) \
0xEE100010 \
| ( (opcode1) << 21 ) \
| ( (crn ) << 16 ) \
| ( (rd ) << 12 ) \
| ( (cp_num ) << 8 ) \
| ( (opcode2) << 5 ) \
| ( crm )
#define DEBUG_MCR_OPCODE(opcode1,crn,rd,cp_num,opcode2,crm) \
0xEE000010 \
| ( (opcode1) << 21 ) \
| ( (crn ) << 16 ) \
| ( (rd ) << 12 ) \
| ( (cp_num ) << 8 ) \
| ( (opcode2) << 5 ) \
| ( crm )
/*
* All blocks sort their adverts by (advert->x.config_flags &
* UNIREGS_SORT_MASK)
*
* When an advert returns true to
* UNIREGS_IS_DEFINITIVE(advert->x.config_flags) then no further
* adverts will be considered. This allows chaining of registers
* within blocks.
*
* Blocks will usually describe with an appropriate enumeration the
* values that the config_flags should take.
*
* The sorting is done in simrdi_manager.c::DemultiplexRegisters()
*
* At the moment, for simulator-defined registers, it is their own
* responsibility that their names do not clash with other adverts.
* This could take place at advert negotiation time. */
#define UNIREGS_IN_BLOCK(unireg) ((unireg)&0x7FF)
#define UNIREGS_BLOCK_NUMBER_MASK (0xF800)
#define UNIREGS_BLOCK_NUMBER(config_flags) \
( (((uint32)(config_flags)) & UNIREGS_BLOCK_NUMBER_MASK) >> 11 )
#define UNIREGS_IS_DEFINITIVE_MASK (0x10)
#define UNIREGS_IS_DEFINITIVE(config_flags) (!!((config_flags) & UNIREGS_IS_DEFINITIVE_MASK))
#define UNIREGS_SORT_MASK (0xF)
/* see simulator-added register blocks */
#define UNIREGS_DO_NOT_AUTO_GENERATE_REG_WIN (0x20)
/*
* Block 0
*
* Block zero contains, eight sub-blocks, the sub-block number should
* be x.config_flags & 0x700. The bottom 4 bits (mask) 0xF are used
* for sorting. The UNIREGS_SUBBLOCK_MASK corresponds to the bits of
* the uniregs number for the subblock number. At the moment the
* SimRdi_Manager does not use the subblock number to optimise the
* access, however, it may in the future so it is an error not to
* now. */
#define UNIREGS_SUBBLOCK_MASK (0x700)
/* Blocks 1 and 2 is the MCRR/MRRC blocks or uniregs.
*
* With the ARM1136, we have new CP15 registers that use MCRR to write
* to them to invalidate or prefetch various ranges. The blocks 15-31
* are essentially encodings of the MCR/MRC opcode space. Thus in
* order to distinguish the MCRR/MRRC instruction space then we need
* new blocks.
*
* The MCRR/MRCC instructions have 8 bits of freedom, thus for all
* coprocessors we need to provide two blocks:
*
* Block 1: MCRR/MRCC extension space, coprocessors 0-7
* FEDCB A98 7654 3210
* block cp op crm
* 00001 cp op crm
*
* Block 2: MCRR/MRCC extension space, coprocessors 8-15
* FEDCB A98 7654 3210
* block cp-8 op crm
* 00010 cp-8 op crm
*
* We now have the possibility of several coprocessors chaining off
* each other in then it is necessary to be careful about returning
* 'can't' when the coprocessor number doesn't match.
*
* Note that this operation is encoding the transfer of two 32 bit
* words, however, RVD will give us a _host_ endian 64 bit quantity
* and so we define that the most significant word is Rn and the least
* significant word is Rd to form the instruction:
* MCRR <copro>, <opcode>, <Rd>, <Rn>, <CRm>
*
* The config_flags used should be the same as
* Uniregs_Config_Block16_Block31 (see later). Each handler should
* explicitly test for the coprocessor register using
* if (UNIREGS_X_CPNUM(unireg) == my_copro_number)
* {
* #if defined(HOST_ENDIAN_BIG)
* // swap to little-endian
* ARMword temp = data[1];
* data[1] = data[0];
* data[0] = temp;
* #elif defined(HOST_ENDIAN_LITTLE)
* // do nothing
* #else
* #error "Cannot determine endianness"
* #endif
* ...; // do it
* }
* else
* {
* return 1; // bounce
* }
*/
/* compose a unireg number in the extension space from cpnum, opcode
and crm */
#define ARMREGNUM_XUNIREG(cpnum, opcode, crm) \
( ((0x8+(cpnum))<<8) | (((opcode)<<4) & 0xF0) | ((crm) & 0xF))
/* given that it is in the extension space figure out what coprocessor
it is for */
#define UNIREGS_X_CPNUM(unireg) ( (((unireg) >> 8) - 0x8) & 0xF )
/* make a MCRR/MRCC instruction from the unireg number */
#define DEBUG_MCRR_FROM_UNIREG(unireg) ( (((unireg)-(0x8<<8)) & 0xFFF) \
| 0xec401000 )
#define DEBUG_MRRC_FROM_UNIREG(unireg) ( (((unireg)-(0x8<<8)) & 0xFFF) \
| 0xec501000 )
/*
* Blocks 16 to 31 (Coprocessors)
*
* A coprocessor can provide uniregs or the core can provide the
* uniregs. If more than one coprocessor registers against the same
* block then the list will be sorted by the numerical value of
* (config_flags & UNIREGS_SORT_MASK). Thus chainable coprocessors
* will be first, the non-chainable one(s), followed by the core and
* then codesequences.
*
* If there is a copro or a core or a codeseq then if any of them fail
* then the others will not be attempted if they exist.
*
* Cores and codeseqs might register as backup options, but if they
* exist then they provide definitive answers as too whether a unireg
* exists and/or is accessible. A copro is also considered definitive
* and if a core or codeseq exists then it will not be used. A
* chainable coprocessor is considered non-definitive and a will chain
* through all the (chainable_)copros until it finds a definitive
* handler. This allows uniregs and non-uniregs coprocessors exist
* simultaneously. The core or codeseq will pick them up.
*
* Chainable and non-chainable coprocessor can exist on the same
* chain. This might be useful if a single register is served by more
* than one coprocessor. The chainable coprocessor adverts will be
* serviced first and they will bit manipulate the destination but
* will return non-zero to bounce the request down to the next
* (chainable) coprocessor. When it eventually hits the coprocessor
* entry, then it will fill in the remaining parts and then return
* that it serviced it (0).
*
* Some of the simulator blocks will automatically be converted into
* register windows. If you don't want them appearing in the window
* then you should set the UNIREGS_DO_NOT_AUTO_GENERATE_REG_WIN flag
* in advert->x.config_flags. Typically this is because they export
* their own window. If an advert advertises more than one register
* then they will be grouped under */
enum Uniregs_Config_Block16_Block31 {
uniregs_codeseq = 1 | UNIREGS_IS_DEFINITIVE_MASK,
/* the thing registering performs a codeseq, note that this need not
be a general codeseq but one specificly geared to copro access */
uniregs_core = 3 | UNIREGS_IS_DEFINITIVE_MASK,
/* the thing registering is the core */
uniregs_copro = 5, /* non-chainable coprocessor */
uniregs_chainable_copro = 7 /* the copro can chain */
};
/*
* Block uniregs_cycle_counter
*
* This block is for cycle counters to advertise their willingness to
* provide cycle-counts.
*
* Because of the importance of cycle counters in RVD for profiling
* this should be cycle counters that would have meaning. Thus an
* I-cycle counter should not go here. What will happen is that
* services that need a cycle counter will, during advert negotiation,
* search this list for a cycle counter, by virtue of it being sorted
* then it will pick the first one that applies to it. At the moment
* this will simply pick the topmost as we don't support multi-cores
* but in the future should check that their cores correspond.
*
* As the absolute register number used in RVD is not exposed then we
* have to walk the co_container to find the number. The comparison
* is done on handle_for_function, _SimReg and start_reg_number.
* While it is not impossible to define more than one cycle counter
* with the single advert, only the first will be taken and the rest
* will be available to the user but will not be used to count
* cycles.
*
* Cycle counters are assumed to have the properties SIMFLG_CYCLES |
* SIMFLG_CYC_REAL | SIMFLG_CYC_ALWAYS | SIMFLG_CYC_OFFSET (in
* simabs.h). In the future we may allow support for other than this,
* but at the moment this is hardwired in SimRdi_Manager.
*
* For information to help people choose the sort number in x.config_flags
* record what values you use here:
* armulext/SimabsMemCallback -- uniregs_cycle_counter -- 0xF
* -- currently assumes that it is the
* -- master cycle counter. It will have to
* -- be modified if it is not. */
#endif /* UNIREGS_REGISTRATION_EVENT_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -