You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							498 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							498 lines
						
					
					
						
							12 KiB
						
					
					
				| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | |
| <HTML | |
| ><HEAD | |
| ><TITLE | |
| >Emulator Objects</TITLE | |
| ><META | |
| NAME="GENERATOR" | |
| CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK | |
| REL="HOME" | |
| TITLE="Bochs Developers Guide" | |
| HREF="index.html"><LINK | |
| REL="UP" | |
| TITLE="About the code" | |
| HREF="about-the-code.html"><LINK | |
| REL="PREVIOUS" | |
| TITLE="Directory Structure" | |
| HREF="directory-structure.html"><LINK | |
| REL="NEXT" | |
| TITLE="Configure Scripting" | |
| HREF="configure-scripting.html"></HEAD | |
| ><BODY | |
| CLASS="SECTION" | |
| BGCOLOR="#FFFFFF" | |
| TEXT="#000000" | |
| LINK="#0000FF" | |
| VLINK="#840084" | |
| ALINK="#0000FF" | |
| ><DIV | |
| CLASS="NAVHEADER" | |
| ><TABLE | |
| SUMMARY="Header navigation table" | |
| WIDTH="100%" | |
| BORDER="0" | |
| CELLPADDING="0" | |
| CELLSPACING="0" | |
| ><TR | |
| ><TH | |
| COLSPAN="3" | |
| ALIGN="center" | |
| >Bochs Developers Guide</TH | |
| ></TR | |
| ><TR | |
| ><TD | |
| WIDTH="10%" | |
| ALIGN="left" | |
| VALIGN="bottom" | |
| ><A | |
| HREF="directory-structure.html" | |
| ACCESSKEY="P" | |
| >Prev</A | |
| ></TD | |
| ><TD | |
| WIDTH="80%" | |
| ALIGN="center" | |
| VALIGN="bottom" | |
| >Chapter 2. About the code</TD | |
| ><TD | |
| WIDTH="10%" | |
| ALIGN="right" | |
| VALIGN="bottom" | |
| ><A | |
| HREF="configure-scripting.html" | |
| ACCESSKEY="N" | |
| >Next</A | |
| ></TD | |
| ></TR | |
| ></TABLE | |
| ><HR | |
| ALIGN="LEFT" | |
| WIDTH="100%"></DIV | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H1 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="EMULATOR-OBJECTS" | |
| >2.3. Emulator Objects</A | |
| ></H1 | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H2 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="AEN175" | |
| >2.3.1. Weird macros and other mysteries</A | |
| ></H2 | |
| ><P | |
| >Bochs has many macros with inscrutable names. One might even go as far as to | |
| say that Bochs is macro infested. | |
| Some of them are gross speed hacks, to cover up the slow speed that C++ causes. | |
| Others paper over differences between the simulated PC configurations. | |
| Many of the macros exhibit the same problem as C++ does: too much stuff happens | |
| behind the programmer's back. More explicitness would be a big win.</P | |
| ></DIV | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H2 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="STATIC-METHODS-HACK" | |
| >2.3.2. Static methods hack</A | |
| ></H2 | |
| ><P | |
| >C++ methods have an invisible parameter called the this pointer - otherwise the | |
| method wouldn't know which object to operate on. In many cases in Bochs, there | |
| will only ever be one object - so this flexibility is unnecessary. There is a | |
| hack that can be enabled by #defining BX_USE_CPU_SMF to 1 in <TT | |
| CLASS="FILENAME" | |
| >config.h</TT | |
| > that makes most methods static, which means they have a "special | |
| relationship" with the class they are declared in but apart from that are | |
| normal C functions with no hidden parameters. Of course they still need access | |
| to the internals of an object, so the single object of their class has a globally | |
| visible name that these functions use. It is all hidden with macros.</P | |
| ><P | |
| >Declaration of a class, from iodev/pic.h:</P | |
| ><TABLE | |
| BORDER="0" | |
| BGCOLOR="#E0E0E0" | |
| WIDTH="100%" | |
| ><TR | |
| ><TD | |
| ><PRE | |
| CLASS="SCREEN" | |
| >... | |
| #if BX_USE_PIC_SMF | |
| #  define BX_PIC_SMF  static | |
| #  define BX_PIC_THIS thePic-> | |
| #else | |
| #  define BX_PIC_SMF | |
| #  define BX_PIC_THIS this-> | |
| #endif | |
| ... | |
| class bx_pic_c : public bx_pic_stub_c { | |
| 
 | |
| public: | |
|   bx_pic_c(void); | |
|   ~bx_pic_c(void); | |
| ... | |
|   BX_PIC_SMF void   service_master_pic(void); | |
|   BX_PIC_SMF void   service_slave_pic(void); | |
|   BX_PIC_SMF void   clear_highest_interrupt(bx_pic_t *pic); | |
|   };</PRE | |
| ></TD | |
| ></TR | |
| ></TABLE | |
| ><P | |
| >And iodev/pic.cc:</P | |
| ><TABLE | |
| BORDER="0" | |
| BGCOLOR="#E0E0E0" | |
| WIDTH="100%" | |
| ><TR | |
| ><TD | |
| ><PRE | |
| CLASS="SCREEN" | |
| >... | |
| #define LOG_THIS thePic-> | |
| ... | |
| bx_pic_c *thePic = NULL; | |
| ... | |
|   void | |
| bx_pic_c::service_master_pic(void) | |
| { | |
|   Bit8u unmasked_requests; | |
|   int irq; | |
|   Bit8u isr, max_irq; | |
|   Bit8u highest_priority = BX_PIC_THIS s.master_pic.lowest_priority + 1; | |
|   if(highest_priority > 7) | |
|     highest_priority = 0; | |
| 
 | |
|   if (BX_PIC_THIS s.master_pic.INT) { /* last interrupt still not acknowleged */ | |
|     return; | |
|     } | |
| 
 | |
|   if (BX_PIC_THIS s.master_pic.special_mask) { | |
|     /* all priorities may be enabled.  check all IRR bits except ones | |
|      * which have corresponding ISR bits set | |
|      */ | |
|     max_irq = highest_priority; | |
|     } | |
|   else { /* normal mode */ | |
|     /* Find the highest priority IRQ that is enabled due to current ISR */ | |
|     isr = BX_PIC_THIS s.master_pic.isr; | |
| ... | |
| } | |
| ...</PRE | |
| ></TD | |
| ></TR | |
| ></TABLE | |
| ><P | |
| >Ugly, isn't it? If we use static methods, methods prefixed with BX_PIC_SMF are | |
| declared static and references to fields inside the object, which are prefixed | |
| with BX_PIC_THIS, will use the globally visible object, thePic->. If we don't | |
| use static methods, BX_PIC_SMF evaluates to nothing and BX_PIC_THIS becomes this->. | |
| Making it evaluate to nothing would be a lot cleaner, but then the scoping rules | |
| would change slightly between the two Bochs configurations, which would be a load | |
| of bugs just waiting to happen. Some classes use BX_SMF, others have their own | |
| version of the macro, like BX_PIC_SMF above.</P | |
| ></DIV | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H2 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="CPU-MEM-OBJECTS" | |
| >2.3.3. CPU und memory objects in UP/SMP configurations</A | |
| ></H2 | |
| ><P | |
| >The CPU class is a special case of the above: if Bochs is simulating a uni- | |
| processor machine then there is obviously only one bx_cpu_c object and the | |
| static methods trick can be used. If, on the other hand, Bochs is simulating an | |
| smp machine then we can't use the trick. The same seems to be true for memory: | |
| for some reason, we have a memory object for each CPU object. This might become | |
| relevant for NUMA machines, but they are not all that common -- and even the | |
| existing IA-32 NUMA machines bend over backwards to hide that fact: it should | |
| only be visible in slightly worse timing for non-local memory and non-local | |
| peripherals. Other than that, the memory map and device map presented to each | |
| CPU will be identical.</P | |
| ><P | |
| >In a UP configuration, the CPU object is declared as bx_cpu. In an SMP | |
| configuration it will be an array of pointers to CPU objects (bx_cpu_array[]). | |
| For memory that would be bx_mem and bx_mem_array[], respectively. | |
| Each CPU object contains a pointer to its associated memory object. | |
| Access of a CPU object often goes through the BX_CPU(x) macro, which either | |
| ignores the parameter and evaluates to &bx_cpu, or evaluates to bx_cpu_array | |
| [n], so the result will always be a pointer. The same goes for BX_MEM(x). | |
| If static methods are used then BX_CPU_THIS_PTR evaluates to BX_CPU(0)->. Ugly, | |
| isn't it?</P | |
| ></DIV | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H2 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="CONFIG-PARAMETER-TREE" | |
| >2.3.4. The configuration parameter tree</A | |
| ></H2 | |
| ><P | |
| >Starting with version 1.3, the Bochs configuration parameters are stored in parameter | |
| objects. These objects have get/set methods with min/max checks and it is possible | |
| to define parameter handlers to perform side effects and to override settings. | |
| Each parameter type has it's own object type with specific features (numeric, | |
| boolean, enum, string and file name). A special object type containing a list of | |
| parameters is designed for building and managing configuration menus or dialogs | |
| automatically. In the original implementation the parameters could be accessed | |
| only with their unique id from a static list or a special structure containing | |
| pointers to all parameters.</P | |
| ><P | |
| >Starting with version 2.3, the Bochs parameter object handling has been rewritten | |
| to a parameter tree. There is now a root list containing child lists, and these | |
| lists can contain lists or parameters and so on. The parameters are now accessed | |
| by a name build from all the list names in the path and finally the parameter | |
| name separated by periods. | |
| <TABLE | |
| BORDER="0" | |
| BGCOLOR="#E0E0E0" | |
| WIDTH="100%" | |
| ><TR | |
| ><TD | |
| ><PRE | |
| CLASS="SCREEN" | |
| >Bit32u megs = SIM->get_param_num("memory.standard.ram.size")->get();</PRE | |
| ></TD | |
| ></TR | |
| ></TABLE | |
| ></P | |
| ><P | |
| >The example above shows how to get the memory size in megabytes from the simulator | |
| interface. In the root list (".") there is child list named "memory" containing | |
| a child list "standard". It's child list "ram" contains the numeric parameter type | |
| "size". The SIM->get_param_num() methods returns the object pointer and the get() | |
| method returns the parameter value.</P | |
| ><P | |
| >The table below shows all parameter types used by the Bochs configuration interface. | |
| <DIV | |
| CLASS="TABLE" | |
| ><A | |
| NAME="AEN198" | |
| ></A | |
| ><P | |
| ><B | |
| >Table 2-2. Parameter types</B | |
| ></P | |
| ><TABLE | |
| BORDER="1" | |
| CLASS="CALSTABLE" | |
| ><COL><COL><THEAD | |
| ><TR | |
| ><TH | |
| >Type</TH | |
| ><TH | |
| >Description</TH | |
| ></TR | |
| ></THEAD | |
| ><TBODY | |
| ><TR | |
| ><TD | |
| >bx_object_c</TD | |
| ><TD | |
| >Base class for all the other parameter types. It contains the unique parameter id and the object type value.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_c</TD | |
| ><TD | |
| >Generic parameter class. It contains the name, label, description and the input/output formats.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_num_c</TD | |
| ><TD | |
| >Numerical (decimal/hex) config settings are stored in this parameter type.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_bool_c</TD | |
| ><TD | |
| >This parameter type is based on bx_param_num_c, but it is designed for boolean values. A dependency | |
| list can be defined to enable/disable other parameters depending on the value change.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_enum_c</TD | |
| ><TD | |
| >Based on bx_param_num_c this parameter type contains a list of valid values.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_string_c</TD | |
| ><TD | |
| >Configuration strings are stored in this type of parameter.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_param_filename_c</TD | |
| ><TD | |
| >Based on bx_param_string_c this parameter type is used for file names.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_list_c</TD | |
| ><TD | |
| >Contains a list of pointers to parameters (bx_param_*_c and bx_list_c). | |
| In the config interface it is used for menus/dialogs.</TD | |
| ></TR | |
| ></TBODY | |
| ></TABLE | |
| ></DIV | |
| ></P | |
| ></DIV | |
| ><DIV | |
| CLASS="SECTION" | |
| ><H2 | |
| CLASS="SECTION" | |
| ><A | |
| NAME="SAVE-RESTORE" | |
| >2.3.5. The save/restore feature</A | |
| ></H2 | |
| ><P | |
| >The save/restore feature is based on an extension to the parameter tree concept. | |
| A subtree (list) called "bochs" appears in the root of the parameter tree | |
| and some new "shadow" parameter types store pointers to values instead of the values | |
| itself. All the hardware objects have register_state() methods to register pointers | |
| to the device registers and switches that need to be saved. The simulator interface | |
| saves the registered data in text format to the specified folder (usually one file | |
| per item in the save/restore list). Large binary arrays are registered with a | |
| special parameter type, so they are saved as separate files.</P | |
| ><P | |
| >The table below shows the additional parameter types for save/restore. | |
| <DIV | |
| CLASS="TABLE" | |
| ><A | |
| NAME="AEN234" | |
| ></A | |
| ><P | |
| ><B | |
| >Table 2-3. Save/restore parameter types</B | |
| ></P | |
| ><TABLE | |
| BORDER="1" | |
| CLASS="CALSTABLE" | |
| ><COL><COL><THEAD | |
| ><TR | |
| ><TH | |
| >Type</TH | |
| ><TH | |
| >Description</TH | |
| ></TR | |
| ></THEAD | |
| ><TBODY | |
| ><TR | |
| ><TD | |
| >bx_shadow_num_c</TD | |
| ><TD | |
| >Based on bx_param_num_c this type stores a pointer to a numerical variable.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_shadow_bool_c</TD | |
| ><TD | |
| >This parameter type stores a pointer to a boolean variable.</TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| >bx_shadow_data_c</TD | |
| ><TD | |
| >This special parameter type stores pointer size of a binary array.</TD | |
| ></TR | |
| ></TBODY | |
| ></TABLE | |
| ></DIV | |
| > | |
| It is also possible to use the bx_param_num_c object with parameter save/restore | |
| handlers. With this special way several device settings can be save to and restored | |
| from one single parameter.</P | |
| ><P | |
| >All devices can uses these two save/restore specific methods: | |
| <P | |
| ></P | |
| ><UL | |
| ><LI | |
| ><P | |
| >register_state() is called after the device init() to register the device members for save/restore</P | |
| ></LI | |
| ><LI | |
| ><P | |
| >after_restore_state() is an optional method to do things directly after restore</P | |
| ></LI | |
| ></UL | |
| ></P | |
| ></DIV | |
| ></DIV | |
| ><DIV | |
| CLASS="NAVFOOTER" | |
| ><HR | |
| ALIGN="LEFT" | |
| WIDTH="100%"><TABLE | |
| SUMMARY="Footer navigation table" | |
| WIDTH="100%" | |
| BORDER="0" | |
| CELLPADDING="0" | |
| CELLSPACING="0" | |
| ><TR | |
| ><TD | |
| WIDTH="33%" | |
| ALIGN="left" | |
| VALIGN="top" | |
| ><A | |
| HREF="directory-structure.html" | |
| ACCESSKEY="P" | |
| >Prev</A | |
| ></TD | |
| ><TD | |
| WIDTH="34%" | |
| ALIGN="center" | |
| VALIGN="top" | |
| ><A | |
| HREF="index.html" | |
| ACCESSKEY="H" | |
| >Home</A | |
| ></TD | |
| ><TD | |
| WIDTH="33%" | |
| ALIGN="right" | |
| VALIGN="top" | |
| ><A | |
| HREF="configure-scripting.html" | |
| ACCESSKEY="N" | |
| >Next</A | |
| ></TD | |
| ></TR | |
| ><TR | |
| ><TD | |
| WIDTH="33%" | |
| ALIGN="left" | |
| VALIGN="top" | |
| >Directory Structure</TD | |
| ><TD | |
| WIDTH="34%" | |
| ALIGN="center" | |
| VALIGN="top" | |
| ><A | |
| HREF="about-the-code.html" | |
| ACCESSKEY="U" | |
| >Up</A | |
| ></TD | |
| ><TD | |
| WIDTH="33%" | |
| ALIGN="right" | |
| VALIGN="top" | |
| >Configure Scripting</TD | |
| ></TR | |
| ></TABLE | |
| ></DIV | |
| ></BODY | |
| ></HTML | |
| > |