SIM_INTERFACE(spr) { void (*register_user_handlers)( conf_object_t *cpu, int64 spr_number, gen_spr_user_getter_func_t getter, lang_void *user_getter_data, gen_spr_user_setter_func_t setter, lang_void *user_setter_data, int privilege_checks); void (*unregister_user_handlers)( conf_object_t *cpu, int64 spr_number); void (*set_target_value)( conf_object_t *cpu, uint64 value); void (*stash_value)( conf_object_t *cpu, int64 spr_number, uint64 value); uint64 (*fetch_value)( conf_object_t *cpu, int64 spr_number); gen_spr_ret_t (*default_getter)( conf_object_t *cpu, int64 spr_number, gen_spr_access_type_t type); gen_spr_ret_t (*default_setter)( conf_object_t *cpu, int64 spr_number, uint64 value, gen_spr_access_type_t type); const char *(*get_name)( conf_object_t *cpu, int64 spr_number); int64 (*get_number)( conf_object_t *cpu, const char *spr_name); }; #define SPR_INTERFACE "spr"
The register_spr_user_handlers function will register user implemented get and set functions that will be called every time a read or write access is made to the SPR with number spr. The getter and setter function is of the following type:
typedef gen_spr_ret_t (*gen_spr_user_getter_func_t)( conf_object_t *cpu, int64 spr_number, gen_spr_access_type_t type, lang_void *user_data);
The type parameter in the get and set functions is one of the following, depending on where from the access originated:
typedef enum { /* Access from a mfspr/mtspr instruction */ Sim_Gen_Spr_Instruction_Access, /* Access through attribute */ Sim_Gen_Spr_Attribute_Access, /* Access through int_register interface */ Sim_Gen_Spr_Int_Register_Access, /* For compatibility with former PPC-only implementation */ Sim_PPC_Spr_Instruction_Access = Sim_Gen_Spr_Instruction_Access, Sim_PPC_Spr_Attribute_Access = Sim_Gen_Spr_Attribute_Access, Sim_PPC_Spr_Int_Register_Access = Sim_Gen_Spr_Int_Register_Access } gen_spr_access_type_t;
Both the get and the set functions must return one of these enum values:
typedef enum { Sim_Gen_Spr_Ok, /* SPR access was OK */ Sim_Gen_Spr_Illegal, /* SPR access should trigger illegal insn exc */ Sim_Gen_Spr_Privilege, /* SPR access should trigger privilege exc */ Sim_Gen_Spr_Processor_Sleeps, /* SPR access suspends the processor */ /* For compatibility with former PPC-only implementation */ Sim_PPC_Spr_Ok = Sim_Gen_Spr_Ok, Sim_PPC_Spr_Illegal = Sim_Gen_Spr_Illegal, Sim_PPC_Spr_Privilege = Sim_Gen_Spr_Privilege } gen_spr_ret_t;
If privilege_checks is not zero, Simics will do privilege checks when a mfspr/mtspr instruction is executed. If this does not produce the desired results, you can register the SPR handlers with privilege_checks set to zero, and do you own checks in your handlers.
The function unregister_spr_user_handlers will remove any registered user handlers for a particular SPR.
The function spr_set_target_value should be called from the get function. The value will be written to the target register for instruction accesses, and returned for attribute and int register interface accesses. If this function is not called, the target register is not changed for instruction accesses (and the mfspr thus acts as a nop).
The functions spr_stash_value and spr_fetch_value can be used to store a SPR value in the processor. This is useful if only the getter (or only the setter) has been overridden with a user handler.
Sometimes it may be desirable to let the processor take care of the access. The functions spr_default_getter and spr_default_setter exist for this purpose.
The function spr_get_name takes spr_number as parameter and returns the name of the SPR.
The function spr_get_number takes the spr_name and returns the SPR number, or -1 if the register does not exist.
Note that the following registers cannot be overridden with user handlers: xer, lr and ctr.
register_user_handlers |
Global Context |
unregister_user_handlers |
Global Context |
set_target_value | Cell Context |
stash_value | Cell Context |
fetch_value | Cell Context |
default_getter | Cell Context |
default_setter | Cell Context |
get_name | Cell Context |
get_number | Cell Context |